summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.ahub/sam/exclude.txt3
-rw-r--r--.ahub/tcchecker-tca/config.yaml88
-rw-r--r--.github/workflows/run-onert-micro-unit-tests.yml47
-rw-r--r--Makefile.template32
-rw-r--r--compiler/CMakeLists.txt4
-rw-r--r--compiler/arser/CMakeLists.txt2
-rw-r--r--compiler/circle-eval-diff/src/InputDataLoader.cpp8
-rw-r--r--compiler/circle-inspect/CMakeLists.txt8
-rw-r--r--compiler/circle-inspect/requires.cmake2
-rw-r--r--compiler/circle-interpreter-test/CMakeLists.txt18
-rw-r--r--compiler/circle-interpreter-test/requires.cmake1
-rw-r--r--compiler/circle-mpqsolver/CMakeLists.txt19
-rw-r--r--compiler/circle-mpqsolver/README.md4
-rw-r--r--compiler/circle-mpqsolver/src/CircleMPQSolver.cpp63
-rw-r--r--compiler/circle-mpqsolver/src/MPQSolver.cpp5
-rw-r--r--compiler/circle-mpqsolver/src/MPQSolver.h8
-rw-r--r--compiler/circle-mpqsolver/src/bisection/BisectionSolver.cpp102
-rw-r--r--compiler/circle-mpqsolver/src/bisection/BisectionSolver.h18
-rw-r--r--compiler/circle-mpqsolver/src/bisection/DepthParameterizer.test.cpp2
-rw-r--r--compiler/circle-mpqsolver/src/bisection/ErrorApproximator.cpp387
-rw-r--r--compiler/circle-mpqsolver/src/bisection/ErrorApproximator.test.cpp136
-rw-r--r--compiler/circle-mpqsolver/src/bisection/VISQErrorApproximator.cpp29
-rw-r--r--compiler/circle-mpqsolver/src/bisection/VISQErrorApproximator.h4
-rw-r--r--compiler/circle-mpqsolver/src/bisection/VISQErrorApproximator.test.cpp83
-rw-r--r--compiler/circle-mpqsolver/src/core/Dumper.cpp160
-rw-r--r--compiler/circle-mpqsolver/src/core/Dumper.h113
-rw-r--r--compiler/circle-mpqsolver/src/core/DumpingHooks.cpp62
-rw-r--r--compiler/circle-mpqsolver/src/core/DumpingHooks.h84
-rw-r--r--compiler/circle-mpqsolver/src/core/ErrorMetric.cpp (renamed from compiler/circle-mpqsolver/src/bisection/ErrorMetric.cpp)7
-rw-r--r--compiler/circle-mpqsolver/src/core/ErrorMetric.h (renamed from compiler/circle-mpqsolver/src/bisection/ErrorMetric.h)10
-rw-r--r--compiler/circle-mpqsolver/src/core/ErrorMetric.test.cpp56
-rw-r--r--compiler/circle-mpqsolver/src/core/Evaluator.cpp (renamed from compiler/circle-mpqsolver/src/bisection/Evaluator.cpp)7
-rw-r--r--compiler/circle-mpqsolver/src/core/Evaluator.h (renamed from compiler/circle-mpqsolver/src/bisection/Evaluator.h)10
-rw-r--r--compiler/circle-mpqsolver/src/core/Quantizer.cpp (renamed from compiler/circle-mpqsolver/src/bisection/Quantizer.cpp)9
-rw-r--r--compiler/circle-mpqsolver/src/core/Quantizer.h (renamed from compiler/circle-mpqsolver/src/bisection/Quantizer.h)25
-rw-r--r--compiler/circle-mpqsolver/src/core/Quantizer.test.cpp (renamed from compiler/circle-mpqsolver/src/bisection/Quantizer.test.cpp)8
-rw-r--r--compiler/circle-mpqsolver/src/core/SolverHooks.cpp (renamed from onert-micro/luci-interpreter/pal/linux/PALFill.h)10
-rw-r--r--compiler/circle-mpqsolver/src/core/SolverHooks.h69
-rw-r--r--compiler/circle-mpqsolver/src/core/SolverOutput.cpp47
-rw-r--r--compiler/circle-mpqsolver/src/core/SolverOutput.h58
-rw-r--r--compiler/circle-mpqsolver/src/core/TestHelper.h (renamed from compiler/circle-mpqsolver/src/bisection/TestHelper.h)0
-rw-r--r--compiler/circle-operator/CMakeLists.txt8
-rw-r--r--compiler/circle-operator/requires.cmake2
-rw-r--r--compiler/circle-opselector/driver/Driver.cpp6
-rw-r--r--compiler/circle-opselector/src/OpSelector.cpp19
-rw-r--r--compiler/circle-part-value-test/CMakeLists.txt12
-rw-r--r--compiler/circle-quantizer-dredd-recipe-test/CMakeLists.txt19
-rw-r--r--compiler/circle-quantizer-dredd-recipe-test/test.lst12
-rw-r--r--compiler/circle-quantizer/src/CircleQuantizer.cpp27
-rw-r--r--compiler/circle-tensordump/CMakeLists.txt8
-rw-r--r--compiler/circle-tensordump/requires.cmake2
-rw-r--r--compiler/circle-tensordump/src/Dump.cpp4
-rw-r--r--compiler/circle-verify/CMakeLists.txt8
-rw-r--r--compiler/circle-verify/requires.cmake2
-rw-r--r--compiler/circle2circle-dredd-recipe-test/test.lst6
-rw-r--r--compiler/circle2circle/src/Circle2Circle.cpp42
-rw-r--r--compiler/circlechef/CMakeLists.txt6
-rw-r--r--compiler/circlechef/circle/CMakeLists.txt4
-rw-r--r--compiler/circlechef/core/CMakeLists.txt2
-rw-r--r--compiler/circlechef/requires.cmake2
-rw-r--r--compiler/circledump/CMakeLists.txt10
-rw-r--r--compiler/circledump/README.md2
-rw-r--r--compiler/circledump/requires.cmake2
-rw-r--r--compiler/circledump/src/MetadataPrinter.h1
-rw-r--r--compiler/circledump/src/OpPrinter.cpp27
-rw-r--r--compiler/common-artifacts/CMakeLists.txt91
-rw-r--r--compiler/common-artifacts/exclude.lst12
-rw-r--r--compiler/dalgona-test/CMakeLists.txt13
-rw-r--r--compiler/dalgona/src/Dalgona.cpp5
-rw-r--r--compiler/dalgona/src/PostOperatorHook.h20
-rw-r--r--compiler/dalgona/src/Utils.cpp22
-rw-r--r--compiler/dalgona/src/Utils.h2
-rw-r--r--compiler/dio-hdf5/include/dio_hdf5/HDF5Importer.h5
-rw-r--r--compiler/dio-hdf5/src/HDF5Importer.cpp11
-rw-r--r--compiler/dio-hdf5/src/HDF5Importer.test.cpp23
-rw-r--r--compiler/loco/CMakeLists.txt2
-rw-r--r--compiler/luci-eval-driver/src/EvalDriver.cpp7
-rw-r--r--compiler/luci-interpreter/include/luci_interpreter/core/Tensor.h4
-rw-r--r--compiler/luci-interpreter/pal/linux/KernelsToBuild.lst6
-rw-r--r--compiler/luci-interpreter/pal/linux/PALGelu.h (renamed from onert-micro/luci-interpreter/pal/linux/PALElu.h)18
-rw-r--r--compiler/luci-interpreter/pal/linux/PALHardSwish.h (renamed from onert-micro/luci-interpreter/pal/linux/PALLeakyRelu.h)14
-rw-r--r--compiler/luci-interpreter/pal/linux/pal.cmake63
-rw-r--r--compiler/luci-interpreter/src/core/KernelParams.h6
-rw-r--r--compiler/luci-interpreter/src/kernels/FloorMod.cpp132
-rw-r--r--compiler/luci-interpreter/src/kernels/FloorMod.h (renamed from onert-micro/luci-interpreter/src/kernels/Less.h)20
-rw-r--r--compiler/luci-interpreter/src/kernels/FloorMod.test.cpp446
-rw-r--r--compiler/luci-interpreter/src/kernels/Gelu.cpp63
-rw-r--r--compiler/luci-interpreter/src/kernels/Gelu.h (renamed from onert-micro/luci-interpreter/src/kernels/Exp.h)16
-rw-r--r--compiler/luci-interpreter/src/kernels/Gelu.test.cpp115
-rw-r--r--compiler/luci-interpreter/src/kernels/HardSwish.cpp52
-rw-r--r--compiler/luci-interpreter/src/kernels/HardSwish.h (renamed from onert-micro/luci-interpreter/src/kernels/Elu.h)13
-rw-r--r--compiler/luci-interpreter/src/kernels/HardSwish.test.cpp81
-rw-r--r--compiler/luci-interpreter/src/kernels/Log.cpp56
-rw-r--r--compiler/luci-interpreter/src/kernels/Log.h (renamed from onert-micro/luci-interpreter/src/kernels/Relu6.h)14
-rw-r--r--compiler/luci-interpreter/src/kernels/Log.test.cpp71
-rw-r--r--compiler/luci-interpreter/src/kernels/Reshape.cpp24
-rw-r--r--compiler/luci-interpreter/src/kernels/Reshape.test.cpp36
-rw-r--r--compiler/luci-interpreter/src/kernels/Select.cpp100
-rw-r--r--compiler/luci-interpreter/src/kernels/Select.h (renamed from onert-micro/luci-interpreter/src/kernels/Greater.h)30
-rw-r--r--compiler/luci-interpreter/src/kernels/Select.test.cpp106
-rw-r--r--compiler/luci-interpreter/src/kernels/Sub.cpp2
-rw-r--r--compiler/luci-interpreter/src/kernels/Sum.cpp179
-rw-r--r--compiler/luci-interpreter/src/kernels/Sum.h (renamed from onert-micro/luci-interpreter/src/kernels/Shape.h)20
-rw-r--r--compiler/luci-interpreter/src/kernels/Sum.test.cpp145
-rw-r--r--compiler/luci-interpreter/src/kernels/TransposeConv.test.cpp5
-rw-r--r--compiler/luci-interpreter/src/loader/KernelBuilder.test.cpp2
-rw-r--r--compiler/luci-interpreter/src/loader/nodes/FloorMod.cpp (renamed from onert-micro/luci-interpreter/src/loader/nodes/Floor.cpp)19
-rw-r--r--compiler/luci-interpreter/src/loader/nodes/Gelu.cpp (renamed from onert-micro/luci-interpreter/src/loader/nodes/PRelu.cpp)21
-rw-r--r--compiler/luci-interpreter/src/loader/nodes/HardSwish.cpp (renamed from onert-micro/luci-interpreter/src/loader/nodes/LessEqual.cpp)21
-rw-r--r--compiler/luci-interpreter/src/loader/nodes/Log.cpp (renamed from onert-micro/luci-interpreter/src/loader/nodes/Exp.cpp)18
-rw-r--r--compiler/luci-interpreter/src/loader/nodes/Select.cpp (renamed from onert-micro/luci-interpreter/src/loader/nodes/Cast.cpp)20
-rw-r--r--compiler/luci-interpreter/src/loader/nodes/Sum.cpp54
-rw-r--r--compiler/luci-interpreter/src/loader/nodes/TransposeConv.cpp7
-rw-r--r--compiler/luci-pass-value-test/CMakeLists.txt13
-rw-r--r--compiler/luci-pass-value-test/test.lst1
-rw-r--r--compiler/luci-value-test/CMakeLists.txt26
-rw-r--r--compiler/luci-value-test/test.lst23
-rw-r--r--compiler/luci/export/CMakeLists.txt4
-rw-r--r--compiler/luci/export/src/CircleBuiltinTypesExtractor.h8
-rw-r--r--compiler/luci/export/src/CircleOps.lst2
-rw-r--r--compiler/luci/import/CMakeLists.txt4
-rw-r--r--compiler/luci/import/include/luci/Import/NodeBuilder.h1
-rw-r--r--compiler/luci/import/include/luci/Import/Nodes.h2
-rw-r--r--compiler/luci/import/include/luci/Import/Nodes/CircleGelu.h37
-rw-r--r--compiler/luci/import/include/luci/Import/Nodes/CircleHardSwish.h37
-rw-r--r--compiler/luci/import/src/GraphBuilderRegistry.cpp13
-rw-r--r--compiler/luci/import/src/Nodes/CircleGelu.cpp44
-rw-r--r--compiler/luci/import/src/Nodes/CircleHardSwish.cpp41
-rw-r--r--compiler/luci/import/src/Nodes/CircleReshape.cpp7
-rw-r--r--compiler/luci/import/src/Nodes/CircleTransposeConv.cpp1
-rw-r--r--compiler/luci/lang/include/luci/IR/CircleNodes.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/CircleNodes.lst2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleGelu.h47
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleHardSwish.h40
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleTransposeConv.h1
-rw-r--r--compiler/luci/lang/src/Nodes/CircleGelu.test.cpp81
-rw-r--r--compiler/luci/lang/src/Nodes/CircleHardSwish.test.cpp76
-rw-r--r--compiler/luci/logex/src/CircleNodeSummaryBuilder.cpp18
-rw-r--r--compiler/luci/logex/src/CircleNodeSummaryBuilder.test.cpp8
-rw-r--r--compiler/luci/logex/src/CircleNodeSummaryBuilders.cpp9
-rw-r--r--compiler/luci/logex/src/CircleNodeSummaryBuilders.h10
-rw-r--r--compiler/luci/partition/CMakeLists.txt2
-rw-r--r--compiler/luci/partition/include/luci/ConnectNode.h2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleGelu.cpp (renamed from onert-micro/luci-interpreter/src/loader/nodes/While.cpp)28
-rw-r--r--compiler/luci/partition/src/Nodes/CircleGelu.test.cpp90
-rw-r--r--compiler/luci/partition/src/Nodes/CircleHardSwish.cpp38
-rw-r--r--compiler/luci/partition/src/Nodes/CircleHardSwish.test.cpp90
-rw-r--r--compiler/luci/partition/src/Nodes/CircleTransposeConv.test.cpp1
-rw-r--r--compiler/luci/pass/include/luci/CircleOptimizer.h2
-rw-r--r--compiler/luci/pass/include/luci/CircleQuantizer.h1
-rw-r--r--compiler/luci/pass/include/luci/DynamicBatchToSingleBatch.h29
-rw-r--r--compiler/luci/pass/include/luci/Pass/DecomposeHardSwishPass.h (renamed from onert-micro/luci-interpreter/src/loader/nodes/If.cpp)27
-rw-r--r--compiler/luci/pass/include/luci/Pass/DynamicBatchToSingleBatchPass.h39
-rw-r--r--compiler/luci/pass/include/luci/Pass/FuseGeluPass.h39
-rw-r--r--compiler/luci/pass/include/luci/Pass/QuantizeWeightsPass.h70
-rw-r--r--compiler/luci/pass/include/luci/Pass/RequantizePass.h2
-rw-r--r--compiler/luci/pass/src/CircleOptimizer.cpp42
-rw-r--r--compiler/luci/pass/src/CircleQuantizer.cpp39
-rw-r--r--compiler/luci/pass/src/ConvertNCHWToNHWCPass.cpp26
-rw-r--r--compiler/luci/pass/src/ConvertNCHWToNHWCPass.test.cpp8
-rw-r--r--compiler/luci/pass/src/ConvertToFakeQuantizedModelPass.cpp4
-rw-r--r--compiler/luci/pass/src/DecomposeHardSwishPass.cpp147
-rw-r--r--compiler/luci/pass/src/DecomposeHardSwishPass.test.cpp205
-rw-r--r--compiler/luci/pass/src/DynamicBatchToSingleBatch.cpp51
-rw-r--r--compiler/luci/pass/src/DynamicBatchToSingleBatchPass.cpp78
-rw-r--r--compiler/luci/pass/src/DynamicBatchToSingleBatchPass.test.cpp126
-rw-r--r--compiler/luci/pass/src/FoldAddV2Pass.test.cpp8
-rw-r--r--compiler/luci/pass/src/FoldCastPass.test.cpp4
-rw-r--r--compiler/luci/pass/src/FoldDequantizePass.test.cpp4
-rw-r--r--compiler/luci/pass/src/FuseActivationFunctionPass.cpp5
-rw-r--r--compiler/luci/pass/src/FuseAddWithFullyConnectedPass.test.cpp54
-rw-r--r--compiler/luci/pass/src/FuseAddWithTConvPass.cpp3
-rw-r--r--compiler/luci/pass/src/FuseBatchNormWithTConvPass.cpp6
-rw-r--r--compiler/luci/pass/src/FuseGeluPass.cpp347
-rw-r--r--compiler/luci/pass/src/FuseGeluPass.test.cpp251
-rw-r--r--compiler/luci/pass/src/PropagateQParamBackwardPass.cpp63
-rw-r--r--compiler/luci/pass/src/PropagateQParamBackwardPass.test.cpp143
-rw-r--r--compiler/luci/pass/src/QuantizationUtils.cpp19
-rw-r--r--compiler/luci/pass/src/QuantizationUtils.h8
-rw-r--r--compiler/luci/pass/src/QuantizeActivation.cpp10
-rw-r--r--compiler/luci/pass/src/QuantizeActivation.h3
-rw-r--r--compiler/luci/pass/src/QuantizeBias.test.cpp47
-rw-r--r--compiler/luci/pass/src/QuantizeDequantizeWeightsPass.cpp8
-rw-r--r--compiler/luci/pass/src/QuantizePreCheckerPass.test.cpp1
-rw-r--r--compiler/luci/pass/src/QuantizeWeights.cpp9
-rw-r--r--compiler/luci/pass/src/QuantizeWeightsOnly.cpp224
-rw-r--r--compiler/luci/pass/src/QuantizeWeightsOnly.h51
-rw-r--r--compiler/luci/pass/src/QuantizeWeightsPass.cpp46
-rw-r--r--compiler/luci/pass/src/QuantizeWeightsPass.test.cpp123
-rw-r--r--compiler/luci/pass/src/QuantizeWithMinMaxPass.cpp16
-rw-r--r--compiler/luci/pass/src/QuantizedModelVerifier.test.cpp73
-rw-r--r--compiler/luci/pass/src/ReplaceNonConstFCWithBatchMatMulPass.test.cpp52
-rw-r--r--compiler/luci/pass/src/ReplaceSubWithAddPass.cpp2
-rw-r--r--compiler/luci/pass/src/RequantizePass.cpp159
-rw-r--r--compiler/luci/pass/src/RequantizePass.test.cpp156
-rw-r--r--compiler/luci/pass/src/ResolveCustomOpMatMulPass.cpp58
-rw-r--r--compiler/luci/pass/src/SubstituteSplitVToSplitPass.test.cpp51
-rw-r--r--compiler/luci/pass/src/VerifyQuantizedBiasScale.cpp2
-rw-r--r--compiler/luci/pass/src/VerifyQuantizedNodeGranularity.h14
-rw-r--r--compiler/luci/pass/src/VerifyQuantizedNodeType.cpp15
-rw-r--r--compiler/luci/pass/src/VerifyQuantizedNodeType.h2
-rw-r--r--compiler/luci/pass/src/helpers/CreateCircleConst.cpp (renamed from onert-micro/luci-interpreter/pal/cmsisnn/PALFill.h)11
-rw-r--r--compiler/luci/pass/src/helpers/CreateCircleConst.h88
-rw-r--r--compiler/luci/pass/src/helpers/TypeMapper.h5
-rw-r--r--compiler/luci/requires.cmake2
-rw-r--r--compiler/luci/service/include/luci/Service/CircleShapeInference.h1
-rw-r--r--compiler/luci/service/include/luci/Service/CircleTypeInference.h1
-rw-r--r--compiler/luci/service/include/luci/Service/Validate.h4
-rw-r--r--compiler/luci/service/src/CircleCloneNode.h2
-rw-r--r--compiler/luci/service/src/CircleShapeInferenceRule.cpp20
-rw-r--r--compiler/luci/service/src/CircleTypeInferenceRule.cpp10
-rw-r--r--compiler/luci/service/src/Nodes/CircleGelu.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CircleGelu.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleHardSwish.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleHardSwish.test.cpp74
-rw-r--r--compiler/luci/service/src/Nodes/CircleTransposeConv.cpp1
-rw-r--r--compiler/luci/service/src/Nodes/CircleTransposeConv.test.cpp12
-rw-r--r--compiler/luci/service/src/ShapeInfer_StridedSlice.cpp97
-rw-r--r--compiler/luci/service/src/Validate.cpp92
-rw-r--r--compiler/luci/tests/test.lst4
-rw-r--r--compiler/mio-circle05/CMakeLists.txt52
-rw-r--r--compiler/mio-circle05/README.md3
-rw-r--r--compiler/mio-circle05/example.cpp41
-rw-r--r--compiler/mio-circle05/include/mio_circle/Helper.h54
-rw-r--r--compiler/mio-circle05/include/mio_circle/Reader.h101
-rw-r--r--compiler/mio-circle05/src/Helper.cpp110
-rw-r--r--compiler/mio-circle05/src/Helper.test.cpp153
-rw-r--r--compiler/mio-circle05/src/Reader.cpp147
-rw-r--r--compiler/mio-circle05/src/Reader.test.cpp60
-rw-r--r--compiler/mio-circle06/CMakeLists.txt52
-rw-r--r--compiler/mio-circle06/README.md3
-rw-r--r--compiler/mio-circle06/example.cpp41
-rw-r--r--compiler/mio-circle06/include/mio_circle/Helper.h54
-rw-r--r--compiler/mio-circle06/include/mio_circle/Reader.h101
-rw-r--r--compiler/mio-circle06/src/Helper.cpp110
-rw-r--r--compiler/mio-circle06/src/Helper.test.cpp153
-rw-r--r--compiler/mio-circle06/src/Reader.cpp147
-rw-r--r--compiler/mio-circle06/src/Reader.test.cpp60
-rw-r--r--compiler/mio-tflite2121/CMakeLists.txt60
-rw-r--r--compiler/mio-tflite2121/README.md3
-rw-r--r--compiler/mio-tflite2121/example.cpp41
-rw-r--r--compiler/mio-tflite2121/include/mio_tflite2121/Helper.h37
-rw-r--r--compiler/mio-tflite2121/src/Helper.cpp104
-rw-r--r--compiler/mio-tflite2121/src/Helper.test.cpp159
-rw-r--r--compiler/mir/unittests/ShapeRange.cpp2
-rw-r--r--compiler/moco-tf/src/Canonicalization/SoftmaxCanonicalizer.h2
-rw-r--r--compiler/nnc/backends/soft_backend/code_snippets/cpp_header_types.def2
-rw-r--r--compiler/nnc/backends/soft_backend/code_snippets/eigen.def2
-rw-r--r--compiler/one-cmds/CMakeLists.txt21
-rw-r--r--compiler/one-cmds/dummy-driver/CMakeLists.txt36
-rw-r--r--compiler/one-cmds/dummy-driver/src/dummy-onnx-ext.cpp (renamed from compiler/circle-mpqsolver/src/bisection/ErrorApproximator.h)33
-rw-r--r--compiler/one-cmds/dummy-driver/src/dummyV2-compile.cpp51
-rw-r--r--compiler/one-cmds/dummy-driver/src/dummyV2-profile.cpp36
-rw-r--r--compiler/one-cmds/dummy-driver/src/dummyV3-profile.cpp38
-rw-r--r--compiler/one-cmds/one-codegen175
-rw-r--r--compiler/one-cmds/one-import-onnx182
-rw-r--r--compiler/one-cmds/one-import-pytorch3
-rw-r--r--compiler/one-cmds/one-infer39
-rw-r--r--compiler/one-cmds/one-init42
-rw-r--r--compiler/one-cmds/one-prepare-venv22
-rw-r--r--compiler/one-cmds/one-prepare-venv.aarch64139
-rw-r--r--compiler/one-cmds/one-prepare-venv.u1804 (renamed from compiler/one-cmds/one-prepare-venv.u2204)19
-rw-r--r--compiler/one-cmds/one-profile120
-rw-r--r--compiler/one-cmds/one-quantize304
-rw-r--r--compiler/one-cmds/onecc57
-rw-r--r--compiler/one-cmds/onelib/CfgRunner.py7
-rw-r--r--compiler/one-cmds/onelib/backends.py79
-rw-r--r--compiler/one-cmds/onelib/constant.py7
-rw-r--r--compiler/one-cmds/onelib/utils.py26
-rw-r--r--compiler/one-cmds/requires.cmake1
-rw-r--r--compiler/one-cmds/tests/one-codegen_neg_001.test2
-rw-r--r--compiler/one-cmds/tests/one-codegen_neg_002.test41
-rw-r--r--compiler/one-cmds/tests/one-codegen_neg_003.test41
-rw-r--r--compiler/one-cmds/tests/one-codegen_neg_004.cfg6
-rw-r--r--compiler/one-cmds/tests/one-codegen_neg_004.test43
-rw-r--r--compiler/one-cmds/tests/one-codegen_neg_005.test41
-rw-r--r--compiler/one-cmds/tests/one-import-onnx_ext_001.test53
-rw-r--r--compiler/one-cmds/tests/one-import_neg_001.test5
-rw-r--r--compiler/one-cmds/tests/one-profile_neg_002.test41
-rw-r--r--compiler/one-cmds/tests/one-profile_neg_003.test41
-rw-r--r--compiler/one-cmds/tests/one-profile_neg_004.cfg6
-rw-r--r--compiler/one-cmds/tests/one-profile_neg_004.test43
-rw-r--r--compiler/one-cmds/tests/one-profile_neg_005.test41
-rw-r--r--compiler/one-cmds/tests/one-quantize_016.test4
-rw-r--r--compiler/one-cmds/tests/one-quantize_017.test46
-rw-r--r--compiler/one-cmds/tests/one-quantize_018.test51
-rw-r--r--compiler/one-cmds/tests/one-quantize_019.test51
-rw-r--r--compiler/one-cmds/tests/one-quantize_020.test51
-rw-r--r--compiler/one-cmds/tests/one-quantize_021.test47
-rw-r--r--compiler/one-cmds/tests/one-quantize_neg_003.test2
-rw-r--r--compiler/one-cmds/tests/one-quantize_neg_022.test48
-rw-r--r--compiler/one-cmds/tests/one-quantize_neg_023.test49
-rw-r--r--compiler/one-cmds/tests/onecc_045.test4
-rw-r--r--compiler/one-cmds/tests/onecc_046.cfg7
-rw-r--r--compiler/one-cmds/tests/onecc_046.test58
-rw-r--r--compiler/one-cmds/tests/onecc_047.cfg7
-rw-r--r--compiler/one-cmds/tests/onecc_047.test59
-rw-r--r--compiler/one-cmds/tests/onecc_048.cfg6
-rw-r--r--compiler/one-cmds/tests/onecc_048.test49
-rw-r--r--compiler/one-cmds/tests/onecc_049.cfg7
-rw-r--r--compiler/one-cmds/tests/onecc_049.test54
-rw-r--r--compiler/one-cmds/tests/onecc_050.cfg7
-rw-r--r--compiler/one-cmds/tests/onecc_050.test54
-rw-r--r--compiler/one-cmds/tests/onecc_051.cfg6
-rw-r--r--compiler/one-cmds/tests/onecc_051.test48
-rw-r--r--compiler/one-cmds/tests/onecc_052.cfg13
-rw-r--r--compiler/one-cmds/tests/onecc_052.test74
-rw-r--r--compiler/one-cmds/tests/onecc_053.cfg13
-rw-r--r--compiler/one-cmds/tests/onecc_053.test74
-rw-r--r--compiler/one-cmds/tests/onecc_054.cfg7
-rw-r--r--compiler/one-cmds/tests/onecc_054.test65
-rw-r--r--compiler/one-cmds/tests/onecc_055.cfg6
-rw-r--r--compiler/one-cmds/tests/onecc_055.test57
-rw-r--r--compiler/one-cmds/tests/onecc_056.cfg6
-rw-r--r--compiler/one-cmds/tests/onecc_056.test48
-rw-r--r--compiler/one-cmds/tests/onecc_057.cfg7
-rw-r--r--compiler/one-cmds/tests/onecc_057.test51
-rw-r--r--compiler/one-cmds/tests/onecc_058.cfg9
-rw-r--r--compiler/one-cmds/tests/onecc_058.test41
-rw-r--r--compiler/one-cmds/tests/onecc_neg_027.cfg7
-rw-r--r--compiler/one-cmds/tests/onecc_neg_027.test43
-rw-r--r--compiler/one-cmds/tests/onecc_neg_028.cfg9
-rw-r--r--compiler/one-cmds/tests/onecc_neg_028.test43
-rw-r--r--compiler/one-cmds/tests/onecc_neg_029.cfg6
-rw-r--r--compiler/one-cmds/tests/onecc_neg_029.test43
-rw-r--r--compiler/one-cmds/tests/onecc_neg_030.cfg6
-rw-r--r--compiler/one-cmds/tests/onecc_neg_030.test43
-rw-r--r--compiler/one-cmds/tests/onecc_neg_031.test43
-rw-r--r--compiler/one-cmds/tests/onecc_neg_031.workflow.json29
-rw-r--r--compiler/one-cmds/tests/onecc_neg_032.cfg7
-rw-r--r--compiler/one-cmds/tests/onecc_neg_032.test43
-rw-r--r--compiler/one-cmds/tests/onecc_neg_033.cfg9
-rw-r--r--compiler/one-cmds/tests/onecc_neg_033.test43
-rw-r--r--compiler/one-cmds/tests/onecc_neg_034.cfg6
-rw-r--r--compiler/one-cmds/tests/onecc_neg_034.test43
-rw-r--r--compiler/one-cmds/tests/onecc_neg_035.cfg6
-rw-r--r--compiler/one-cmds/tests/onecc_neg_035.test43
-rw-r--r--compiler/one-cmds/tests/onecc_neg_036.test43
-rw-r--r--compiler/one-cmds/tests/onecc_neg_036.workflow.json29
-rw-r--r--compiler/one-cmds/tests/prepare_test_materials.sh18
-rw-r--r--compiler/one-cmds/tests/preprocess_images.py7
-rw-r--r--compiler/one-cmds/tests/pytorch-operations/example_generator.py3
-rw-r--r--compiler/onecc-docker/docker/Dockerfile4
-rw-r--r--compiler/onecc-docker/onecc-docker62
-rw-r--r--compiler/oops/requires.cmake1
-rw-r--r--compiler/pics/CMakeLists.txt2
-rw-r--r--compiler/pics/requires.cmake1
-rw-r--r--compiler/pota-quantization-value-test/CMakeLists.txt20
-rwxr-xr-xcompiler/pota-quantization-value-test/compare_tensors.py8
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/channel/int16/wo_quantization/ker.json61
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/channel/int8/wo_quantization/ker.json61
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/channel/int16/wo_quantization/ker.json53
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/channel/int8/wo_quantization/ker.json53
-rw-r--r--compiler/pota-quantization-value-test/requires.cmake1
-rw-r--r--compiler/pota-quantization-value-test/test.lst5
-rwxr-xr-xcompiler/pota-quantization-value-test/test_wo_quantization.sh87
-rw-r--r--compiler/record-minmax-conversion-test/CMakeLists.txt13
-rw-r--r--compiler/record-minmax-thread-safety-test/CMakeLists.txt19
-rw-r--r--compiler/record-minmax/CMakeLists.txt21
-rw-r--r--compiler/record-minmax/driver/Driver.cpp45
-rw-r--r--compiler/record-minmax/include/MinMaxComputer.h85
-rw-r--r--compiler/record-minmax/include/MinMaxObserver.h9
-rw-r--r--compiler/record-minmax/include/MinMaxVectors.h33
-rw-r--r--compiler/record-minmax/include/RecordFunction.h77
-rw-r--r--compiler/record-minmax/include/RecordMinMax.h31
-rw-r--r--compiler/record-minmax/src/MinMaxComputer.cpp86
-rw-r--r--compiler/record-minmax/src/RecordFunction.cpp97
-rw-r--r--compiler/record-minmax/src/RecordMinMax.cpp76
-rw-r--r--compiler/record-minmax/tests/MinMaxComputer.test.cpp75
-rw-r--r--compiler/souschef/include/souschef/Data/Gaussian.h21
-rw-r--r--compiler/souschef/src/Gaussian.cpp18
-rw-r--r--compiler/souschef/src/LexicalCast.cpp7
-rw-r--r--compiler/tf2tfliteV2-conversion-test/CMakeLists.txt7
-rw-r--r--compiler/tfl-inspect/CMakeLists.txt8
-rw-r--r--compiler/tfl-inspect/requires.cmake2
-rw-r--r--compiler/tfl-inspect/src/Reader.cpp2
-rw-r--r--compiler/tfl-verify/CMakeLists.txt6
-rw-r--r--compiler/tfl-verify/requires.cmake2
-rw-r--r--compiler/tflchef/CMakeLists.txt6
-rw-r--r--compiler/tflchef/core/CMakeLists.txt2
-rw-r--r--compiler/tflchef/core/src/Convert.cpp2
-rw-r--r--compiler/tflchef/core/src/CustomOp/Erf.cpp58
-rw-r--r--compiler/tflchef/core/src/CustomOp/Erf.h49
-rw-r--r--compiler/tflchef/core/src/DataChef.def3
-rw-r--r--compiler/tflchef/core/src/ModelChef.cpp19
-rw-r--r--compiler/tflchef/core/src/Op/Gelu.cpp34
-rw-r--r--compiler/tflchef/core/src/Op/Gelu.h46
-rw-r--r--compiler/tflchef/core/src/Op/HardSwish.cpp27
-rw-r--r--compiler/tflchef/core/src/Op/HardSwish.h46
-rw-r--r--compiler/tflchef/core/src/Op/TransposeConv.cpp7
-rw-r--r--compiler/tflchef/core/src/OpChef.def3
-rw-r--r--compiler/tflchef/core/src/OpChefs.h3
-rw-r--r--compiler/tflchef/proto/tflchef.proto7
-rw-r--r--compiler/tflchef/requires.cmake2
-rw-r--r--compiler/tflchef/tests/CMakeLists.txt4
-rw-r--r--compiler/tflchef/tests/custom_erf/test.recipe17
-rw-r--r--compiler/tflchef/tflite/CMakeLists.txt4
-rw-r--r--compiler/tflchef/tflite/src/Convert.cpp2
-rw-r--r--compiler/tflchef/tflite/src/Op/Gelu.cpp46
-rw-r--r--compiler/tflchef/tflite/src/Op/HardSwish.cpp40
-rw-r--r--compiler/tflchef/tflite/src/Op/PRelu.cpp5
-rw-r--r--compiler/tflchef/tflite/src/Op/TransposeConv.cpp2
-rw-r--r--compiler/tflchef/tflite/src/Op/include/Gelu.h39
-rw-r--r--compiler/tflchef/tflite/src/Op/include/HardSwish.h39
-rw-r--r--compiler/tflchef/tflite/src/RecipeChef.cpp2
-rw-r--r--compiler/tflchef/tflite/src/TFliteImport.cpp2
-rw-r--r--compiler/tflchef/tflite/src/TFliteOpChefs.h2
-rw-r--r--compiler/tflchef/tflite/src/TFliteOpRegistry.h2
-rw-r--r--compiler/tfldump/CMakeLists.txt10
-rw-r--r--compiler/tfldump/requires.cmake2
-rw-r--r--compiler/tfldump/src/Dump.cpp2
-rw-r--r--compiler/tfldump/src/OpPrinter.cpp16
-rw-r--r--compiler/tfldump/src/Read.cpp2
-rw-r--r--compiler/tflite2circle/CMakeLists.txt10
-rw-r--r--compiler/tflite2circle/requires.cmake4
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions.h1
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/GeluOptions.cpp32
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/GeluOptions.h31
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/TransposeConvOptions.cpp2
-rw-r--r--compiler/tflite2circle/src/CircleModel.cpp34
-rw-r--r--compiler/tflite2circle/src/TFLBuiltinOptions.lst1
-rw-r--r--compiler/tflite2circle/src/TFLOperator.lst1
-rw-r--r--compiler/vconone/CMakeLists.txt2
-rw-r--r--compiler/vconone/src/version.cpp2
-rw-r--r--compiler/visq-unittest/CMakeLists.txt10
-rw-r--r--compiler/visq-unittest/test/testDotBuilder.py1
-rw-r--r--compiler/visq-unittest/test/testQErrorComputer.py97
-rw-r--r--compiler/visq/CMakeLists.txt2
-rw-r--r--compiler/visq/visq51
-rw-r--r--compiler/visq/visqlib/DumpFP32FM.py36
-rw-r--r--compiler/visq/visqlib/DumpFakeQuantFM.py44
-rw-r--r--compiler/visq/visqlib/QErrorComputer.py112
-rw-r--r--compute/ARMComputeEx/src/runtime/CL/functions/CLSplitVEx.cpp2
-rw-r--r--compute/cker/CMakeLists.txt4
-rw-r--r--compute/cker/include/cker/PortableTensorUtils.h54
-rw-r--r--compute/cker/include/cker/Shape.h2
-rw-r--r--compute/cker/include/cker/Types.h9
-rw-r--r--compute/cker/include/cker/eigen/eigen_gemm_eigen.h95
-rw-r--r--compute/cker/include/cker/operation/Conv.h15
-rw-r--r--compute/cker/include/cker/operation/DepthwiseConv.h1
-rw-r--r--compute/cker/include/cker/operation/Einsum.h6
-rw-r--r--compute/cker/include/cker/operation/FullyConnected.h39
-rw-r--r--compute/cker/include/cker/operation/optimized/Gemm.h100
-rw-r--r--compute/cker/include/cker/operation/reference/Conv.h85
-rw-r--r--compute/cker/include/cker/operation/reference/integer_ops/DepthwiseConvHybrid.h122
-rw-r--r--compute/cker/include/cker/train/operation/FullyConnected.h49
-rw-r--r--compute/cker/include/cker/train/operation/Loss.h77
-rw-r--r--compute/cker/include/cker/train/operation/ReLU.h50
-rw-r--r--compute/cker/src/train/FullyConnected.test.cc83
-rw-r--r--compute/cker/src/train/Loss.test.cc201
-rw-r--r--compute/cker/src/train/Relu.test.cc107
-rw-r--r--compute/ruy/include/ruy/Shape.h2
-rw-r--r--docs/conf.py2
-rw-r--r--docs/howto/how-to-build-compiler.md13
-rw-r--r--docs/howto/how-to-build-runtime.md148
-rw-r--r--docs/howto/how-to-cross-build-runtime-for-arm.md63
-rw-r--r--docs/release/1.23/index.rst13
-rw-r--r--docs/release/1.23/release-note-1.23.0.md8
-rw-r--r--docs/release/1.24/index.rst13
-rw-r--r--docs/release/1.24/release-note-1.24.0.md9
-rw-r--r--docs/release/1.25/index.rst13
-rw-r--r--docs/release/1.25/release-note_1.25.0.md17
-rw-r--r--docs/release/onert-micro/0.1/release-note-0.1.0.md72
-rw-r--r--docs/release/onert-micro/1.0/release-note-1.0.0.md12
-rw-r--r--infra/cmake/packages/AbseilSourceConfig.cmake6
-rw-r--r--infra/cmake/packages/CMSIS-NN-4.1.0/CMSIS-NNConfig.cmake14
-rw-r--r--infra/cmake/packages/CMSIS-NN-4.1.0/CMSIS-NNConfigVersion.cmake10
-rw-r--r--infra/cmake/packages/TensorFlowSource-2.12.1/TensorFlowSourceConfig.cmake19
-rw-r--r--infra/cmake/packages/TensorFlowSource-2.12.1/TensorFlowSourceConfigVersion.cmake10
-rw-r--r--infra/command/build-docker-image6
-rw-r--r--infra/debian/compiler/changelog19
-rw-r--r--infra/debian/compiler/one-compiler.install4
-rwxr-xr-xinfra/debian/compiler/rules2
-rw-r--r--infra/docker/bionic/Dockerfile.aarch6492
-rw-r--r--infra/docker/focal/Dockerfile46
-rw-r--r--infra/docker/focal/Dockerfile.aarch6462
-rw-r--r--infra/docker/jammy/Dockerfile.aarch6460
-rw-r--r--infra/nncc/Makefile.arm324
-rw-r--r--infra/nncc/cmake/buildtool/config/config_aarch64-linux.cmake13
-rw-r--r--infra/nncc/cmake/buildtool/config/config_aarch64-tizen.cmake17
-rw-r--r--infra/nncc/cmake/buildtool/config/config_armv7hl-tizen.cmake29
-rw-r--r--infra/nncc/cmake/buildtool/config/config_armv7l-tizen.cmake29
-rw-r--r--infra/nncc/cmake/buildtool/config/config_i686-tizen.cmake17
-rw-r--r--infra/nncc/cmake/buildtool/config/config_x86_64-tizen.cmake17
-rw-r--r--infra/nncc/cmake/options/options_aarch64-darwin.cmake4
-rw-r--r--infra/nncc/cmake/options/options_aarch64-linux.cmake4
-rw-r--r--infra/nncc/cmake/options/options_aarch64-tizen.cmake4
-rw-r--r--infra/nncc/cmake/options/options_armv7hl-tizen.cmake5
-rw-r--r--infra/nncc/cmake/options/options_armv7l-tizen.cmake5
-rw-r--r--infra/nncc/cmake/options/options_i686-tizen.cmake3
-rw-r--r--infra/nncc/cmake/options/options_x86_64-darwin.cmake4
-rw-r--r--infra/nncc/cmake/options/options_x86_64-tizen.cmake3
-rw-r--r--infra/nnfw/CMakeLists.txt4
-rw-r--r--infra/nnfw/cmake/CfgOptionFlags.cmake3
-rw-r--r--infra/nnfw/cmake/buildtool/config/config_linux.cmake5
-rw-r--r--infra/nnfw/cmake/buildtool/cross/toolchain_armv7l-tizen.cmake56
-rw-r--r--infra/nnfw/cmake/options/options_aarch64-android.cmake2
-rw-r--r--infra/nnfw/cmake/options/options_aarch64-tizen.cmake3
-rw-r--r--infra/nnfw/cmake/options/options_armv7hl-tizen.cmake3
-rw-r--r--infra/nnfw/cmake/options/options_armv7l-tizen.cmake3
-rw-r--r--infra/nnfw/cmake/options/options_i686-tizen.cmake3
-rw-r--r--infra/nnfw/cmake/options/options_x86_64-tizen.cmake3
-rw-r--r--infra/nnfw/cmake/packages/LuciConfig.cmake43
-rw-r--r--infra/packaging/build2
-rw-r--r--infra/packaging/preset/2023041366
-rw-r--r--infra/packaging/preset/20230413_windows80
-rw-r--r--infra/packaging/preset/2023090766
-rw-r--r--infra/packaging/preset/20230907_windows80
-rw-r--r--infra/packaging/res/tf2nnpkg.20230413109
-rw-r--r--infra/packaging/res/tf2nnpkg.20230907109
-rw-r--r--infra/scripts/compiler_modules.sh3
-rwxr-xr-xinfra/scripts/docker_build_nncc.sh2
-rwxr-xr-xinfra/scripts/docker_collect_nnpkg_resources.sh2
-rw-r--r--nnpackage/schema/circle_schema.fbs104
-rw-r--r--onert-micro/CMakeLists.txt87
-rw-r--r--onert-micro/README.md98
-rw-r--r--onert-micro/eval-driver/Driver.cpp2
-rw-r--r--onert-micro/externals/CMakeLists.txt9
-rw-r--r--onert-micro/externals/flatbuffers/base.h453
-rw-r--r--onert-micro/externals/flatbuffers/code_generators.h234
-rw-r--r--onert-micro/externals/flatbuffers/flatbuffers.h3078
-rw-r--r--onert-micro/externals/flatbuffers/flatc.h95
-rw-r--r--onert-micro/externals/flatbuffers/flexbuffers.h1852
-rw-r--r--onert-micro/externals/flatbuffers/grpc.h361
-rw-r--r--onert-micro/externals/flatbuffers/hash.h145
-rw-r--r--onert-micro/externals/flatbuffers/idl.h1145
-rw-r--r--onert-micro/externals/flatbuffers/minireflect.h507
-rw-r--r--onert-micro/externals/flatbuffers/pch/flatc_pch.h40
-rw-r--r--onert-micro/externals/flatbuffers/pch/pch.h39
-rw-r--r--onert-micro/externals/flatbuffers/reflection.h520
-rw-r--r--onert-micro/externals/flatbuffers/reflection_generated.h1257
-rw-r--r--onert-micro/externals/flatbuffers/registry.h140
-rw-r--r--onert-micro/externals/flatbuffers/stl_emulation.h674
-rw-r--r--onert-micro/externals/flatbuffers/util.h799
-rw-r--r--onert-micro/externals/gen/circle-generated/circle/schema_generated.h24984
-rw-r--r--onert-micro/helpers/GenerateKernelsListHelper.cpp14
-rw-r--r--onert-micro/luci-interpreter/CMakeLists.txt8
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/Interpreter.h2
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/TrainingSettings.h70
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/core/Tensor.h117
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/core/reader/CircleMicroReader.h2
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/onert-micro-version.h26
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/TestDataBase.h46
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/abs/FloatAbsKernel.h90
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/abs/NegAbsKernel.h139
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/abs/TestDataAbsBase.h60
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/add/FloatAddKernel.h176
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/add/IntAddKernel.h285
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/add/NegAddKernel.h148
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/add/TestDataAddBase.h68
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/add_n/FloatAddNKernel.h121
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/add_n/NegAddNKernel.h94
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/add_n/TestDataAddNBase.h66
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/argmax/FloatArgMaxKernel.h95
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/argmax/NegArgMaxKernel.h89
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/argmax/TestDataArgMaxBase.h60
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/argmin/FloatArgMinKernel.h95
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/argmin/NegArgMinKernel.h89
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/argmin/TestDataArgMinBase.h60
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/average_pool_2d/FloatAveragePool2DKernel.h103
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/average_pool_2d/NegAveragePool2DKernel.h88
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/average_pool_2d/TestDataAveragePool2DBase.h60
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/concatenation/FloatConcatenationKernel.h105
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/concatenation/IntConcatenationKernel.h168
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/concatenation/NegConcatenationKernel.h215
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/concatenation/TestDataConcatenationBase.h63
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/conv2d/FloatConv2DKernel.h107
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/conv2d/NegConv2DKernel.h231
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/conv2d/TestDataConv2DBase.h58
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/conv2d/U8Conv2DKernel.h117
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/div/FloatDivKernel.h153
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/div/NegDivKernel.h149
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/div/TestDataDivBase.h68
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/elu/FloatEluKernel.h90
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/elu/NegEluKernel.h83
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/elu/TestDataEluBase.h60
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/equal/FloatEqualKernel.h281
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/equal/IntEqualKernel.h278
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/equal/TestDataEqualBase.h68
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/exp/FloatExpKernel.h90
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/exp/NegExpKernel.h84
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/exp/TestDataExpBase.h60
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/expand_dims/ExpandDimsKernel.h179
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/fill/FillKernel.h114
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/fill/NegFillKernel.h152
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/fully_connected/FloatFullyConnectedKernel.h115
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/fully_connected/NegFullyConnectedKernel.h218
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/fully_connected/TestDataFullyConnectedBase.h58
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/fully_connected/U8FullyConnectedKernel.h112
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather/FloatGatherKernel.h96
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather/IntGatherKernel.h92
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather/NegGatherKernel.h214
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather/TestDataGatherBase.h60
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/greater/FloatGreaterKernel.h185
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/greater/TestDataGreaterBase.h68
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/greater_equal/FloatGreaterEqualKernel.h158
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/greater_equal/TestDataGreaterEqualBase.h68
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/leaky_relu/FloatLeakyReLUKernel.h92
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/leaky_relu/NegLeakyReLUKernel.h85
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/leaky_relu/TestDataLeakyReLUBase.h60
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/less/FloatLessKernel.h313
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/less/IntLessKernel.h301
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/less/NegTestDataLessKernel.h91
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/less/QuantLessKernel.h156
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/less/TestDataLessBase.h68
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/less_equal/FloatLessEqualKernel.h185
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/less_equal/TestDataLessEqualBase.h68
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_and/BoolLogicalAndKernel.h104
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_and/NegLogicalAndKernel.h90
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_and/TestDataLogicalAndBase.h63
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_or/BoolLogicalOrKernel.h105
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_or/NegLogicalOrKernel.h90
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_or/TestDataLogicalOrBase.h63
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/logistic/FloatLogisticKernel.h90
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/logistic/NegLogisticKernel.h139
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/logistic/TestDataLogisticBase.h60
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/maxpool2d/FloatMaxPool2DKernel.h107
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/maxpool2d/NegMaxPool2DKernel.h201
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/maxpool2d/TestDataMaxPool2DBase.h60
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/mul/FloatMulKernel.h177
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/mul/IntMulKernel.h172
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/mul/NegMulKernel.h209
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/mul/TestDataMulBase.h68
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/neg/FloatNegKernel.h91
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/neg/NegNegKernel.h145
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/neg/TestDataNegBase.h60
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/notequal/FloatNotEqualKernel.h184
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/notequal/TestDataNotEqualBase.h68
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/pack/PackKernel.h270
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/pack/TestDataPackBase.h63
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/pad/FloatPadKernel.h106
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/pad/NegPadKernel.h92
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/pad/TestDataPadBase.h60
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/pad_v2/FloatPadV2Kernel.h110
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/pad_v2/NegPadV2Kernel.h97
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/pad_v2/TestDataPadV2Base.h60
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/reduce_common/NegReduceProdKernel.h150
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/reduce_common/ReduceProdKernel.h177
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/reduce_common/TestDataReduceCommonBase.h60
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/relu/FloatReLUKernel.h88
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/relu/NegReLUKernel.h83
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/relu/TestDataReLUBase.h60
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/relu6/FloatReLU6Kernel.h88
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/relu6/NegReLU6Kernel.h83
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/relu6/TestDataReLU6Base.h60
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/reshape/ReshapeKernel.h176
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_bilinear/FloatResizeBilinearKernel.h190
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_bilinear/NegResizeBilinearKernel.h461
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_bilinear/TestDataResizeBilinearBase.h61
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_bilinear/U8ResizeBilinearKernel.h208
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/shape/NegShapeKernel.h83
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/shape/ShapeKernel.h113
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/slice/FloatSliceKernel.h99
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/slice/NegSliceKernel.h292
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/slice/QuantS16SliceKernel.h106
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/slice/QuantU8SliceKernel.h106
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/slice/TestDataSliceBase.h60
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/split/FloatSplitKernel.h103
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/split/IntSplitKernel.h99
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/split/TestDataSplitBase.h68
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/split_v/SplitVKernel.h147
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/strided_slice/StridedSliceKernel.h130
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/sub/FloatSubKernel.h177
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/sub/IntSubKernel.h172
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/sub/NegSubKernel.h209
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/sub/TestDataSubBase.h68
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/tanh/FloatTanhKernel.h89
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/tanh/NegTanhKernel.h83
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/tanh/TestDataTanhBase.h60
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/transpose/TransposeKernel.h121
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/unidirectional_lstm/FloatUnidirectionalLSTMKernel.h164
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/unidirectional_lstm/QuantS8UnidirectionalLSTM.h265
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/unidirectional_lstm/TestDataUnidirectionalLSTMBase.h60
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/while/NegWhileKernel.h137
-rw-r--r--onert-micro/luci-interpreter/include/luci_interpreter/test_models/while/WhileKernel.h162
-rw-r--r--onert-micro/luci-interpreter/pal/cmsisnn/PALArgMax.h34
-rw-r--r--onert-micro/luci-interpreter/pal/cmsisnn/PALAveragePool2d.h125
-rw-r--r--onert-micro/luci-interpreter/pal/cmsisnn/PALBatchToSpaceND.h38
-rw-r--r--onert-micro/luci-interpreter/pal/cmsisnn/PALConv2d.h1
-rw-r--r--onert-micro/luci-interpreter/pal/cmsisnn/PALDepthToSpace.h36
-rw-r--r--onert-micro/luci-interpreter/pal/cmsisnn/PALDepthwiseConv2d.h193
-rw-r--r--onert-micro/luci-interpreter/pal/cmsisnn/PALDequantize.h45
-rw-r--r--onert-micro/luci-interpreter/pal/cmsisnn/PALFullyConnected.h1
-rw-r--r--onert-micro/luci-interpreter/pal/cmsisnn/PALL2Normalize.h35
-rw-r--r--onert-micro/luci-interpreter/pal/cmsisnn/PALL2Pool2D.h1
-rw-r--r--onert-micro/luci-interpreter/pal/cmsisnn/PALLeakyRelu.h33
-rw-r--r--onert-micro/luci-interpreter/pal/cmsisnn/PALMul.h1
-rw-r--r--onert-micro/luci-interpreter/pal/cmsisnn/PALQuantize.h45
-rw-r--r--onert-micro/luci-interpreter/pal/cmsisnn/PALResizeBilinear.h38
-rw-r--r--onert-micro/luci-interpreter/pal/cmsisnn/PALResizeNearestNeighbor.h38
-rw-r--r--onert-micro/luci-interpreter/pal/cmsisnn/PALSVDF.h190
-rw-r--r--onert-micro/luci-interpreter/pal/cmsisnn/PALSoftmax.h79
-rw-r--r--onert-micro/luci-interpreter/pal/cmsisnn/PALSpaceToBatchND.h39
-rw-r--r--onert-micro/luci-interpreter/pal/cmsisnn/PALSpaceToDepth.h36
-rw-r--r--onert-micro/luci-interpreter/pal/cmsisnn/PALSub.h1
-rw-r--r--onert-micro/luci-interpreter/pal/cmsisnn/PALreference_ops.h1556
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALAbs.h (renamed from onert-micro/luci-interpreter/pal/cmsisnn/PALElu.h)19
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALAddCommon.h94
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALAddN.h47
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALArgMinMax.h73
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALAveragePool2DCommon.h93
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALComparisons.h176
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALConcatenation.h70
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALConv2DCommon.h201
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALDiv.h115
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALElu.h (renamed from onert-micro/luci-interpreter/pal/mcu/PALElu.h)17
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALExp.h (renamed from onert-micro/luci-interpreter/pal/cmsisnn/PALNeg.h)25
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALFullyConnectedCommon.h103
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALLogicalCommon.h35
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALLogistic.h156
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALMaxPool2DCommon.h146
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALMulCommon.h115
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALNeg.h (renamed from onert-micro/luci-interpreter/pal/linux/PALNeg.h)27
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALPad.h109
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALReduceCommon.h114
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALReluCommon.h41
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALResizeBilinear.h135
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALSoftmax.h78
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALStridedSlice.h260
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALSub.h89
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALTanh.h121
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALTranspose.h104
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALUnidirectionalSequenceLSTMCommon.h567
-rw-r--r--onert-micro/luci-interpreter/pal/common/PALUtils.h182
-rw-r--r--onert-micro/luci-interpreter/pal/common/Params.h214
-rw-r--r--onert-micro/luci-interpreter/pal/common/ProcessBroadcastShapes.h209
-rw-r--r--onert-micro/luci-interpreter/pal/linux/KernelsToBuild.lst77
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALArgMax.h34
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALAveragePool2d.h74
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALBatchMatMul.h68
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALBatchToSpaceND.h38
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALConv2d.h128
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALDepthToSpace.h36
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALDepthwiseConv2d.h92
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALDequantize.h35
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALFullyConnected.h62
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALGather.h36
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALL2Normalize.h35
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALL2Pool2D.h34
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALLocalResponseNormalization.h35
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALLogSoftmax.h48
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALMul.h56
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALQuantize.h45
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALRelu.h40
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALRelu6.h40
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALResizeBilinear.h38
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALResizeNearestNeighbor.h38
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALSVDF.h91
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALSlice.h34
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALSoftmax.h48
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALSpaceToBatchND.h39
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALSpaceToDepth.h36
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALSplit.h34
-rw-r--r--onert-micro/luci-interpreter/pal/linux/PALSub.h36
-rw-r--r--onert-micro/luci-interpreter/pal/linux/pal.cmake82
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/KernelsToBuild.lst38
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALAdd.h41
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALApplyActivationToVector.h75
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALArgMax.h34
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALAveragePool2D.h28
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALAveragePool2d.h74
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALBatchToSpaceND.h38
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALConv2d.h66
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALDepthToSpace.h36
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALDepthwiseConv2d.h92
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALDequantize.h45
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALFullyConnected.h61
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALL2Normalize.h35
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALL2Pool2D.h1
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALLeakyRelu.h33
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALMaxPool2D.h28
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALMul.h26
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALNeg.h33
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALQuantize.h45
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALResizeBilinear.h38
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALResizeNearestNeighbor.h39
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALSVDF.h258
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALSoftmax.h59
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALSpaceToBatchND.h39
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALSpaceToDepth.h36
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALSub.h36
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALUnidirectionalSequenceLSTM.h616
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/PALreference_ops.h1556
-rw-r--r--onert-micro/luci-interpreter/pal/mcu/pal.cmake51
-rw-r--r--onert-micro/luci-interpreter/src/Interpreter.cpp4
-rw-r--r--onert-micro/luci-interpreter/src/core/RuntimeGraph.cpp187
-rw-r--r--onert-micro/luci-interpreter/src/core/RuntimeGraph.h52
-rw-r--r--onert-micro/luci-interpreter/src/core/RuntimeModule.h5
-rw-r--r--onert-micro/luci-interpreter/src/core/reader/CircleMicroReader.cpp2
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Abs.cpp90
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Abs.test.cpp99
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Add.cpp259
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Add.h51
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Add.test.cpp381
-rw-r--r--onert-micro/luci-interpreter/src/kernels/AddN.cpp113
-rw-r--r--onert-micro/luci-interpreter/src/kernels/AddN.test.cpp100
-rw-r--r--onert-micro/luci-interpreter/src/kernels/ArgMax.cpp138
-rw-r--r--onert-micro/luci-interpreter/src/kernels/ArgMax.h45
-rw-r--r--onert-micro/luci-interpreter/src/kernels/ArgMax.test.cpp127
-rw-r--r--onert-micro/luci-interpreter/src/kernels/ArgMin.cpp70
-rw-r--r--onert-micro/luci-interpreter/src/kernels/ArgMin.test.cpp86
-rw-r--r--onert-micro/luci-interpreter/src/kernels/AveragePool2D.cpp218
-rw-r--r--onert-micro/luci-interpreter/src/kernels/AveragePool2D.h55
-rw-r--r--onert-micro/luci-interpreter/src/kernels/AveragePool2D.test.cpp280
-rw-r--r--onert-micro/luci-interpreter/src/kernels/BatchMatMul.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/BatchMatMul.test.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.test.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/BinaryOpCommon.h212
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Builders.h16
-rw-r--r--onert-micro/luci-interpreter/src/kernels/CMakeLists.txt12
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Cast.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Cast.test.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Concatenation.cpp57
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Concatenation.test.cpp280
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Conv2D.cpp197
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Conv2D.test.cpp712
-rw-r--r--onert-micro/luci-interpreter/src/kernels/DepthToSpace.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/DepthToSpace.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/DepthToSpace.test.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/DepthwiseConv2D.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/DepthwiseConv2D.test.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Dequantize.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Dequantize.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Div.cpp159
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Div.h50
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Div.test.cpp244
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Elu.cpp58
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Elu.test.cpp92
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Equal.cpp143
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Equal.h55
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Equal.test.cpp309
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Exp.cpp63
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Exp.test.cpp80
-rw-r--r--onert-micro/luci-interpreter/src/kernels/ExpandDims.cpp6
-rw-r--r--onert-micro/luci-interpreter/src/kernels/ExpandDims.test.cpp112
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Fill.cpp115
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Fill.h48
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Fill.test.cpp169
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Floor.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Floor.test.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/FloorDiv.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/FullyConnected.cpp96
-rw-r--r--onert-micro/luci-interpreter/src/kernels/FullyConnected.test.cpp285
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Gather.cpp173
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Gather.h48
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Gather.test.cpp166
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Greater.cpp146
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Greater.test.cpp327
-rw-r--r--onert-micro/luci-interpreter/src/kernels/GreaterEqual.cpp149
-rw-r--r--onert-micro/luci-interpreter/src/kernels/GreaterEqual.h55
-rw-r--r--onert-micro/luci-interpreter/src/kernels/GreaterEqual.test.cpp326
-rw-r--r--onert-micro/luci-interpreter/src/kernels/If.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/If.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/InstanceNorm.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/InstanceNorm.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/InstanceNorm.test.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/KernelBuilder.cpp38
-rw-r--r--onert-micro/luci-interpreter/src/kernels/KernelBuilder.h109
-rw-r--r--onert-micro/luci-interpreter/src/kernels/L2Normalize.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/L2Normalize.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/L2Pool2D.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/LeakyRelu.cpp97
-rw-r--r--onert-micro/luci-interpreter/src/kernels/LeakyRelu.h54
-rw-r--r--onert-micro/luci-interpreter/src/kernels/LeakyRelu.test.cpp129
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Less.cpp181
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Less.test.cpp347
-rw-r--r--onert-micro/luci-interpreter/src/kernels/LessEqual.cpp147
-rw-r--r--onert-micro/luci-interpreter/src/kernels/LessEqual.h55
-rw-r--r--onert-micro/luci-interpreter/src/kernels/LessEqual.test.cpp327
-rw-r--r--onert-micro/luci-interpreter/src/kernels/LocalResponseNormalization.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/LocalResponseNormalization.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/LogSoftmax.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/LogSoftmax.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/LogicalAnd.cpp70
-rw-r--r--onert-micro/luci-interpreter/src/kernels/LogicalAnd.h48
-rw-r--r--onert-micro/luci-interpreter/src/kernels/LogicalAnd.test.cpp114
-rw-r--r--onert-micro/luci-interpreter/src/kernels/LogicalNot.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/LogicalNot.h47
-rw-r--r--onert-micro/luci-interpreter/src/kernels/LogicalOr.cpp61
-rw-r--r--onert-micro/luci-interpreter/src/kernels/LogicalOr.h44
-rw-r--r--onert-micro/luci-interpreter/src/kernels/LogicalOr.test.cpp117
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Logistic.cpp83
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Logistic.test.cpp164
-rw-r--r--onert-micro/luci-interpreter/src/kernels/MISOKernel.h87
-rw-r--r--onert-micro/luci-interpreter/src/kernels/MaxPool2D.cpp181
-rw-r--r--onert-micro/luci-interpreter/src/kernels/MaxPool2D.test.cpp181
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Maximum.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Mean.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Minimum.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/MirrorPad.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/MirrorPad.test.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Mul.cpp222
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Mul.h53
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Mul.test.cpp313
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Neg.cpp58
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Neg.h47
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Neg.test.cpp97
-rw-r--r--onert-micro/luci-interpreter/src/kernels/NotEqual.cpp147
-rw-r--r--onert-micro/luci-interpreter/src/kernels/NotEqual.h55
-rw-r--r--onert-micro/luci-interpreter/src/kernels/NotEqual.test.cpp299
-rw-r--r--onert-micro/luci-interpreter/src/kernels/OneHot.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/OneHot.test.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/PRelu.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/PRelu.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Pack.cpp160
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Pack.h47
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Pack.test.cpp165
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Pad.cpp95
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Pad.h44
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Pad.test.cpp122
-rw-r--r--onert-micro/luci-interpreter/src/kernels/PadCommon.cpp144
-rw-r--r--onert-micro/luci-interpreter/src/kernels/PadCommon.h (renamed from onert-micro/luci-interpreter/src/loader/nodes/Neg.cpp)24
-rw-r--r--onert-micro/luci-interpreter/src/kernels/PadV2.cpp91
-rw-r--r--onert-micro/luci-interpreter/src/kernels/PadV2.h45
-rw-r--r--onert-micro/luci-interpreter/src/kernels/PadV2.test.cpp111
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Pow.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Pow.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Pow.test.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Quantize.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Quantize.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/ReduceCommon.cpp92
-rw-r--r--onert-micro/luci-interpreter/src/kernels/ReduceCommon.test.cpp107
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Relu.cpp116
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Relu.h52
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Relu.test.cpp163
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Relu6.cpp90
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Relu6.test.cpp144
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Reshape.cpp53
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Reshape.test.cpp85
-rw-r--r--onert-micro/luci-interpreter/src/kernels/ResizeBilinear.cpp109
-rw-r--r--onert-micro/luci-interpreter/src/kernels/ResizeBilinear.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/ResizeBilinear.test.cpp323
-rw-r--r--onert-micro/luci-interpreter/src/kernels/ResizeNearestNeighbor.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/ReverseV2.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/ReverseV2.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Rsqrt.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Rsqrt.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Rsqrt.test.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/SISOKernel.h57
-rw-r--r--onert-micro/luci-interpreter/src/kernels/SVDF.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/SVDF.test.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Shape.cpp55
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Shape.test.cpp86
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Slice.cpp243
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Slice.h45
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Slice.test.cpp142
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Softmax.cpp88
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Softmax.test.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/SpaceToBatchND.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/SpaceToBatchND.test.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/SpaceToDepth.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/SpaceToDepth.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/SpaceToDepth.test.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Split.cpp107
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Split.h73
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Split.test.cpp130
-rw-r--r--onert-micro/luci-interpreter/src/kernels/SplitV.cpp121
-rw-r--r--onert-micro/luci-interpreter/src/kernels/SplitV.h50
-rw-r--r--onert-micro/luci-interpreter/src/kernels/SplitV.test.cpp113
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Sqrt.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Sqrt.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Sqrt.test.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Square.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Square.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/SquaredDifference.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Squeeze.test.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/StridedSlice.cpp189
-rw-r--r--onert-micro/luci-interpreter/src/kernels/StridedSlice.h48
-rw-r--r--onert-micro/luci-interpreter/src/kernels/StridedSlice.test.cpp114
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Sub.cpp245
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Sub.h50
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Sub.test.cpp288
-rw-r--r--onert-micro/luci-interpreter/src/kernels/TISOKernel.h127
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Tanh.cpp209
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Tanh.h53
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Tanh.test.cpp169
-rw-r--r--onert-micro/luci-interpreter/src/kernels/TestUtils.cpp83
-rw-r--r--onert-micro/luci-interpreter/src/kernels/TestUtils.h253
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Transpose.cpp87
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Transpose.h45
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Transpose.test.cpp111
-rw-r--r--onert-micro/luci-interpreter/src/kernels/TransposeConv.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/TransposeConv.test.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/UnidirectionalSequenceLSTM.cpp31
-rw-r--r--onert-micro/luci-interpreter/src/kernels/UnidirectionalSequenceLSTM.h39
-rw-r--r--onert-micro/luci-interpreter/src/kernels/UnidirectionalSequenceLSTM.test.cpp556
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Unpack.cpp1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Unpack.h1
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Utils.cpp48
-rw-r--r--onert-micro/luci-interpreter/src/kernels/Utils.h111
-rw-r--r--onert-micro/luci-interpreter/src/kernels/While.cpp202
-rw-r--r--onert-micro/luci-interpreter/src/kernels/While.h49
-rw-r--r--onert-micro/luci-interpreter/src/kernels/While.test.cpp104
-rw-r--r--onert-micro/luci-interpreter/src/loader/GraphLoader.cpp130
-rw-r--r--onert-micro/luci-interpreter/src/loader/ModuleLoader.cpp16
-rw-r--r--onert-micro/luci-interpreter/src/loader/ModuleLoader.h2
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Add.cpp44
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/ArgMax.cpp44
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/AveragePool2D.cpp57
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/BatchMatMul.cpp55
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/BatchToSpaceND.cpp39
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Concatenation.cpp48
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Conv2D.cpp58
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/DepthToSpace.cpp44
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/DepthwiseConv2D.cpp60
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Dequantize.cpp35
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Div.cpp43
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Elu.cpp35
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Equal.cpp38
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/ExpandDims.cpp37
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Fill.cpp36
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/FloorDiv.cpp36
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/FullyConnected.cpp47
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Gather.cpp45
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Greater.cpp36
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/GreaterEqual.cpp37
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/InstanceNorm.cpp48
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/L2Normalize.cpp44
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/L2Pool2D.cpp48
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/LeakyRelu.cpp44
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Less.cpp37
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/LocalResponseNormalization.cpp46
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/LogSoftmax.cpp36
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/LogicalAnd.cpp38
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/LogicalNot.cpp36
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/LogicalOr.cpp38
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Logistic.cpp36
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/MaxPool2D.cpp49
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Maximum.cpp37
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Mean.cpp57
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Minimum.cpp37
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/MirrorPad.cpp45
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Mul.cpp44
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/NotEqual.cpp37
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/OneHot.cpp46
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Pack.cpp46
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Pad.cpp37
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/PadV2.cpp38
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Pow.cpp37
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Quantize.cpp35
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Relu.cpp35
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Relu6.cpp35
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Reshape.cpp38
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/ResizeBilinear.cpp46
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/ResizeNearestNeighbor.cpp50
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/ReverseV2.cpp38
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Rsqrt.cpp35
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/SVDF.cpp89
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Shape.cpp42
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Slice.cpp38
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Softmax.cpp42
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/SpaceToBatchND.cpp39
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/SpaceToDepth.cpp43
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Split.cpp43
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/SplitV.cpp44
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Sqrt.cpp35
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Square.cpp35
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/SquaredDifference.cpp38
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Squeeze.cpp42
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/StridedSlice.cpp51
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Sub.cpp44
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Tanh.cpp35
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Transpose.cpp38
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/TransposeConv.cpp57
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/UnidirectionalSequenceLSTM.cpp145
-rw-r--r--onert-micro/luci-interpreter/src/loader/nodes/Unpack.cpp49
-rw-r--r--onert-micro/standalone/CMakeLists.txt8
-rw-r--r--packaging/ABSEIL.tar.gzbin1909045 -> 2151177 bytes
-rw-r--r--packaging/FLATBUFFERS-2.0.tar.gzbin345691 -> 407104 bytes
-rw-r--r--packaging/nnfw.spec70
-rw-r--r--res/CircleSchema/0.5/circle_schema.fbs1338
-rw-r--r--res/CircleSchema/0.6/circle_schema.fbs1388
-rwxr-xr-xres/PyTorchExamples/ptem.py6
-rw-r--r--res/TensorFlowLiteRecipes/Gelu_000/test.recipe20
-rw-r--r--res/TensorFlowLiteRecipes/Gelu_000/test.reverse0
-rw-r--r--res/TensorFlowLiteRecipes/HardSwish_000/test.recipe17
-rw-r--r--res/TensorFlowLiteRecipes/HardSwish_000/test.reverse0
-rw-r--r--res/TensorFlowLiteRecipes/HardSwish_001/test.recipe17
-rw-r--r--res/TensorFlowLiteRecipes/HardSwish_001/test.rule8
-rw-r--r--res/TensorFlowLiteRecipes/Net_Gelu_000/test.recipe100
-rw-r--r--res/TensorFlowLiteRecipes/Net_Gelu_000/test.rule8
-rw-r--r--res/TensorFlowLiteRecipes/Net_Gelu_001/test.recipe100
-rw-r--r--res/TensorFlowLiteRecipes/Net_Gelu_001/test.rule8
-rw-r--r--res/TensorFlowLiteRecipes/Net_TConv_Add_000/test.recipe1
-rw-r--r--res/TensorFlowLiteRecipes/Net_TConv_Add_001/test.recipe1
-rw-r--r--res/TensorFlowLiteRecipes/Net_TConv_Add_002/test.recipe1
-rw-r--r--res/TensorFlowLiteRecipes/Net_TConv_BN_000/test.recipe1
-rw-r--r--res/TensorFlowLiteRecipes/Net_TConv_BN_001/test.recipe1
-rw-r--r--res/TensorFlowLiteRecipes/Net_TConv_BN_002/test.recipe1
-rw-r--r--res/TensorFlowLiteRecipes/Net_TConv_BN_003/test.recipe1
-rw-r--r--res/TensorFlowLiteRecipes/Net_TConv_BN_004/test.recipe1
-rw-r--r--res/TensorFlowLiteRecipes/Net_TConv_BN_005/test.recipe1
-rw-r--r--res/TensorFlowLiteRecipes/Quant_Add_I8_000/test.recipe66
-rw-r--r--res/TensorFlowLiteRecipes/Quant_Add_I8_000/test.rule7
-rw-r--r--res/TensorFlowLiteRecipes/Quant_AveragePool2D_I8_000/test.recipe51
-rw-r--r--res/TensorFlowLiteRecipes/Quant_AveragePool2D_I8_000/test.rule6
-rw-r--r--res/TensorFlowLiteRecipes/Quant_Conv_I8_000/test.recipe472
-rw-r--r--res/TensorFlowLiteRecipes/Quant_Conv_I8_000/test.rule8
-rw-r--r--res/TensorFlowLiteRecipes/Quant_DepthwiseConv2D_I8_000/test.recipe473
-rw-r--r--res/TensorFlowLiteRecipes/Quant_DepthwiseConv2D_I8_000/test.rule8
-rw-r--r--res/TensorFlowLiteRecipes/Quant_MaxPool2D_I8_000/test.recipe51
-rw-r--r--res/TensorFlowLiteRecipes/Quant_MaxPool2D_I8_000/test.rule6
-rw-r--r--res/TensorFlowLiteRecipes/Quant_Mean_I8_000/test.recipe63
-rw-r--r--res/TensorFlowLiteRecipes/Quant_Mean_I8_000/test.rule7
-rw-r--r--res/TensorFlowLiteRecipes/Quant_Mul_I8_000/test.recipe66
-rw-r--r--res/TensorFlowLiteRecipes/Quant_Mul_I8_000/test.rule7
-rw-r--r--res/TensorFlowLiteRecipes/Quant_PRelu_I8_000/test.recipe66
-rw-r--r--res/TensorFlowLiteRecipes/Quant_PRelu_I8_000/test.rule7
-rw-r--r--res/TensorFlowLiteRecipes/Quant_ReLU_I8_000/test.recipe43
-rw-r--r--res/TensorFlowLiteRecipes/Quant_ReLU_I8_000/test.rule6
-rw-r--r--res/TensorFlowLiteRecipes/Quant_TransposeConv_000/test.recipe1
-rw-r--r--res/TensorFlowLiteRecipes/Quant_TransposeConv_001/test.recipe1
-rw-r--r--res/TensorFlowLiteRecipes/Quant_TransposeConv_I8_000/test.recipe344
-rw-r--r--res/TensorFlowLiteRecipes/Quant_TransposeConv_I8_000/test.rule8
-rw-r--r--res/TensorFlowLiteRecipes/REGRESS_ONNX_Mul_Mul_000/test.recipe88
-rw-r--r--res/TensorFlowLiteRecipes/REGRESS_ONNX_Mul_Mul_000/test.rule7
-rw-r--r--res/TensorFlowLiteRecipes/TransposeConv_000/test.recipe1
-rw-r--r--res/TensorFlowLiteRecipes/TransposeConv_001/test.recipe1
-rw-r--r--res/TensorFlowLiteSchema/2.10.1/schema.fbs1306
-rw-r--r--res/TensorFlowLiteSchema/2.12.1/schema.fbs1340
-rw-r--r--res/TensorFlowLiteSchema/SCHEMA.lst1
-rw-r--r--runtime/contrib/android/api/build.gradle2
-rw-r--r--runtime/libs/benchmark/include/benchmark/CsvWriter.h1
-rw-r--r--runtime/libs/benchmark/include/benchmark/Phase.h1
-rw-r--r--runtime/libs/benchmark/src/Result.cpp2
-rw-r--r--runtime/onert/CMakeLists.txt1
-rw-r--r--runtime/onert/api/include/nnfw.h10
-rw-r--r--runtime/onert/api/include/nnfw_experimental.h244
-rw-r--r--runtime/onert/api/include/nnfw_version.h2
-rw-r--r--runtime/onert/api/src/nnfw_api.cc130
-rw-r--r--runtime/onert/api/src/nnfw_api_internal.cc440
-rw-r--r--runtime/onert/api/src/nnfw_api_internal.h46
-rw-r--r--runtime/onert/backend/CMakeLists.txt7
-rw-r--r--runtime/onert/backend/acl_cl/Config.cc2
-rw-r--r--runtime/onert/backend/acl_cl/Config.h2
-rw-r--r--runtime/onert/backend/acl_cl/KernelGenerator.cc2
-rw-r--r--runtime/onert/backend/acl_cl/Optimizer.cc2
-rw-r--r--runtime/onert/backend/acl_common/AclTensorManager.h6
-rw-r--r--runtime/onert/backend/acl_neon/Config.cc2
-rw-r--r--runtime/onert/backend/acl_neon/Config.h2
-rw-r--r--runtime/onert/backend/acl_neon/KernelGenerator.cc2
-rw-r--r--runtime/onert/backend/acl_neon/Optimizer.cc2
-rw-r--r--runtime/onert/backend/cl_common/include/cl_common/BackendContext.h6
-rw-r--r--runtime/onert/backend/cpu/BackendContext.cc2
-rw-r--r--runtime/onert/backend/cpu/CMakeLists.txt4
-rw-r--r--runtime/onert/backend/cpu/Config.cc2
-rw-r--r--runtime/onert/backend/cpu/Config.h2
-rw-r--r--runtime/onert/backend/cpu/KernelGenerator.cc2
-rw-r--r--runtime/onert/backend/cpu/ops/ConvolutionLayer.cc74
-rw-r--r--runtime/onert/backend/cpu/ops/ConvolutionLayer.h22
-rw-r--r--runtime/onert/backend/cpu/ops/DepthwiseConvolutionLayer.cc86
-rw-r--r--runtime/onert/backend/cpu/ops/DepthwiseConvolutionLayer.h9
-rw-r--r--runtime/onert/backend/cpu/ops/ElementwiseActivationLayer.h2
-rw-r--r--runtime/onert/backend/cpu/ops/FullyConnectedLayer.cc9
-rw-r--r--runtime/onert/backend/cpu/ops/FullyConnectedLayer.h2
-rw-r--r--runtime/onert/backend/cpu/ops/OperationUtils.cc2
-rw-r--r--runtime/onert/backend/gpu_cl/BackendContext.cc2
-rw-r--r--runtime/onert/backend/gpu_cl/Config.cc2
-rw-r--r--runtime/onert/backend/gpu_cl/Config.h2
-rw-r--r--runtime/onert/backend/gpu_cl/TensorManager.cc4
-rw-r--r--runtime/onert/backend/ruy/BackendContext.cc2
-rw-r--r--runtime/onert/backend/ruy/Config.cc2
-rw-r--r--runtime/onert/backend/ruy/Config.h2
-rw-r--r--runtime/onert/backend/ruy/KernelGenerator.cc2
-rw-r--r--runtime/onert/backend/train/Backend.h72
-rw-r--r--runtime/onert/backend/train/BackendContext.cc112
-rw-r--r--runtime/onert/backend/train/BackendContext.h90
-rw-r--r--runtime/onert/backend/train/CMakeLists.txt20
-rw-r--r--runtime/onert/backend/train/Config.cc32
-rw-r--r--runtime/onert/backend/train/Config.h47
-rw-r--r--runtime/onert/backend/train/ExternalContext.h35
-rw-r--r--runtime/onert/backend/train/KernelGenerator.cc260
-rw-r--r--runtime/onert/backend/train/KernelGenerator.h67
-rw-r--r--runtime/onert/backend/train/MemoryManager.h35
-rw-r--r--runtime/onert/backend/train/Tensor.h55
-rw-r--r--runtime/onert/backend/train/TensorBuilder.cc138
-rw-r--r--runtime/onert/backend/train/TensorBuilder.h77
-rw-r--r--runtime/onert/backend/train/TensorManager.cc155
-rw-r--r--runtime/onert/backend/train/TensorManager.h66
-rw-r--r--runtime/onert/backend/train/TensorRegistry.h38
-rw-r--r--runtime/onert/backend/train/ops/ConvolutionLayer.cc57
-rw-r--r--runtime/onert/backend/train/ops/ConvolutionLayer.h56
-rw-r--r--runtime/onert/backend/train/ops/ElementwiseActivationLayer.cc95
-rw-r--r--runtime/onert/backend/train/ops/ElementwiseActivationLayer.h66
-rw-r--r--runtime/onert/backend/train/ops/FullyConnectedLayer.cc209
-rw-r--r--runtime/onert/backend/train/ops/FullyConnectedLayer.h74
-rw-r--r--runtime/onert/backend/train/ops/GradientApplier.cc52
-rw-r--r--runtime/onert/backend/train/ops/GradientApplier.h54
-rw-r--r--runtime/onert/backend/train/ops/LossLayer.cc99
-rw-r--r--runtime/onert/backend/train/ops/LossLayer.h62
-rw-r--r--runtime/onert/backend/train/ops/OperationUtils.h40
-rw-r--r--runtime/onert/backend/train/ops/PoolLayer.cc72
-rw-r--r--runtime/onert/backend/train/ops/PoolLayer.h59
-rw-r--r--runtime/onert/backend/train/ops/ReshapeLayer.cc61
-rw-r--r--runtime/onert/backend/train/ops/ReshapeLayer.h62
-rw-r--r--runtime/onert/backend/train/train.cc24
-rw-r--r--runtime/onert/backend/trix/BackendContext.cc2
-rw-r--r--runtime/onert/backend/trix/Config.cc2
-rw-r--r--runtime/onert/backend/trix/Config.h2
-rw-r--r--runtime/onert/backend/trix/DevContext.cc12
-rw-r--r--runtime/onert/backend/xnnpack/BackendContext.cc2
-rw-r--r--runtime/onert/backend/xnnpack/Config.cc2
-rw-r--r--runtime/onert/backend/xnnpack/Config.h2
-rw-r--r--runtime/onert/backend/xnnpack/KernelGenerator.cc2
-rw-r--r--runtime/onert/core/CMakeLists.txt31
-rw-r--r--runtime/onert/core/include/backend/IConfig.h6
-rw-r--r--runtime/onert/core/include/backend/basic/BackendContextHelpers.h15
-rw-r--r--runtime/onert/core/include/backend/basic/DynamicTensorManager.h4
-rw-r--r--runtime/onert/core/include/backend/basic/StaticTensorManager.h2
-rw-r--r--runtime/onert/core/include/backend/basic/TensorBuilder.h1
-rw-r--r--runtime/onert/core/include/backend/basic/train/TrainableBackendContextHelpers.h68
-rw-r--r--runtime/onert/core/include/backend/basic/train/TrainableTensor.h98
-rw-r--r--runtime/onert/core/include/backend/train/ITensorRegistry.h246
-rw-r--r--runtime/onert/core/include/backend/train/ITrainableBackend.h42
-rw-r--r--runtime/onert/core/include/backend/train/ITrainableTensor.h53
-rw-r--r--runtime/onert/core/include/backend/train/KernelGeneratorBase.h60
-rw-r--r--runtime/onert/core/include/backend/train/TrainableBackendContext.h100
-rw-r--r--runtime/onert/core/include/compiler/CodeMap.h6
-rw-r--r--runtime/onert/core/include/compiler/CompilerFactory.h4
-rw-r--r--runtime/onert/core/include/compiler/CompilerOptions.h1
-rw-r--r--runtime/onert/core/include/compiler/ILoweredGraph.h42
-rw-r--r--runtime/onert/core/include/compiler/LoweredGraph.h19
-rw-r--r--runtime/onert/core/include/compiler/StaticShapeInferer.h17
-rw-r--r--runtime/onert/core/include/compiler/train/LoweredTrainableGraph.h80
-rw-r--r--runtime/onert/core/include/compiler/train/TrainableCodeMap.h54
-rw-r--r--runtime/onert/core/include/compiler/train/TrainingInfo.h71
-rw-r--r--runtime/onert/core/include/exec/Execution.h20
-rw-r--r--runtime/onert/core/include/exec/FunctionSequence.h2
-rw-r--r--runtime/onert/core/include/exec/MinMaxMap.h39
-rw-r--r--runtime/onert/core/include/exec/train/IGradientApplier.h46
-rw-r--r--runtime/onert/core/include/exec/train/ITrainableFunction.h41
-rw-r--r--runtime/onert/core/include/exec/train/TrainableFnSequence.h52
-rw-r--r--runtime/onert/core/include/exec/train/optimizer/Optimizer.h77
-rw-r--r--runtime/onert/core/include/exec/train/optimizer/OptimizerCode.h53
-rw-r--r--runtime/onert/core/include/exec/train/optimizer/SGD.h83
-rw-r--r--runtime/onert/core/include/ir/Graph.h68
-rw-r--r--runtime/onert/core/include/ir/IGraph.h47
-rw-r--r--runtime/onert/core/include/ir/IOperation.h50
-rw-r--r--runtime/onert/core/include/ir/Model.h68
-rw-r--r--runtime/onert/core/include/ir/NNPkg.h30
-rw-r--r--runtime/onert/core/include/ir/OperandIndexSequence.h1
-rw-r--r--runtime/onert/core/include/ir/Operation.h22
-rw-r--r--runtime/onert/core/include/ir/Operations.Include.h1
-rw-r--r--runtime/onert/core/include/ir/Operations.h4
-rw-r--r--runtime/onert/core/include/ir/Operations.lst3
-rw-r--r--runtime/onert/core/include/ir/operation/BinaryArithmetic.h2
-rw-r--r--runtime/onert/core/include/ir/operation/Loss.h74
-rw-r--r--runtime/onert/core/include/ir/train/ITrainableOperation.h49
-rw-r--r--runtime/onert/core/include/ir/train/Operations.Include.h29
-rw-r--r--runtime/onert/core/include/ir/train/Operations.lst28
-rw-r--r--runtime/onert/core/include/ir/train/TrainableGraph.h145
-rw-r--r--runtime/onert/core/include/ir/train/TrainableOperationVisitor.h43
-rw-r--r--runtime/onert/core/include/ir/train/operation/Conv2D.h51
-rw-r--r--runtime/onert/core/include/ir/train/operation/ElementwiseActivation.h52
-rw-r--r--runtime/onert/core/include/ir/train/operation/FullyConnected.h51
-rw-r--r--runtime/onert/core/include/ir/train/operation/Loss.h51
-rw-r--r--runtime/onert/core/include/ir/train/operation/Permute.h51
-rw-r--r--runtime/onert/core/include/ir/train/operation/Pool2D.h51
-rw-r--r--runtime/onert/core/include/ir/train/operation/Reshape.h51
-rw-r--r--runtime/onert/core/include/ir/train/operation/Softmax.h51
-rw-r--r--runtime/onert/core/include/ir/train/operation/UntrainableOperation.h63
-rw-r--r--runtime/onert/core/include/odc/IQuantizer.h36
-rw-r--r--runtime/onert/core/include/odc/QuantizeManager.h81
-rw-r--r--runtime/onert/core/include/util/Config.lst1
-rw-r--r--runtime/onert/core/include/util/MinMaxMap.h47
-rw-r--r--runtime/onert/core/include/util/Set.h16
-rw-r--r--runtime/onert/core/include/util/Utils.h57
-rw-r--r--runtime/onert/core/src/backend/BackendContext.cc2
-rw-r--r--runtime/onert/core/src/backend/basic/StaticTensorManager.cc9
-rw-r--r--runtime/onert/core/src/backend/basic/Tensor.cc2
-rw-r--r--runtime/onert/core/src/backend/basic/TensorBuilder.cc8
-rw-r--r--runtime/onert/core/src/backend/basic/train/TrainableTensor.cc49
-rw-r--r--runtime/onert/core/src/backend/builtin/Backend.h28
-rw-r--r--runtime/onert/core/src/backend/builtin/BackendContext.cc2
-rw-r--r--runtime/onert/core/src/backend/builtin/Config.cc2
-rw-r--r--runtime/onert/core/src/backend/builtin/Config.h2
-rw-r--r--runtime/onert/core/src/backend/builtin/KernelGenerator.cc8
-rw-r--r--runtime/onert/core/src/backend/builtin/kernel/WhileLayer.cc4
-rw-r--r--runtime/onert/core/src/backend/builtin/train/BackendContext.cc78
-rw-r--r--runtime/onert/core/src/backend/builtin/train/BackendContext.h76
-rw-r--r--runtime/onert/core/src/backend/builtin/train/KernelGenerator.cc98
-rw-r--r--runtime/onert/core/src/backend/builtin/train/KernelGenerator.h75
-rw-r--r--runtime/onert/core/src/backend/builtin/train/Tensor.h40
-rw-r--r--runtime/onert/core/src/backend/builtin/train/TensorRegistry.h132
-rw-r--r--runtime/onert/core/src/backend/builtin/train/kernel/PermuteLayer.cc85
-rw-r--r--runtime/onert/core/src/backend/builtin/train/kernel/PermuteLayer.h60
-rw-r--r--runtime/onert/core/src/compiler/Compiler.cc38
-rw-r--r--runtime/onert/core/src/compiler/CompilerFactory.cc15
-rw-r--r--runtime/onert/core/src/compiler/CompilerHelpers.h52
-rw-r--r--runtime/onert/core/src/compiler/CompilerOptions.cc1
-rw-r--r--runtime/onert/core/src/compiler/ExecutorFactory.cc452
-rw-r--r--runtime/onert/core/src/compiler/ExecutorFactory.h66
-rw-r--r--runtime/onert/core/src/compiler/Fp32ToFp16Converter.cc4
-rw-r--r--runtime/onert/core/src/compiler/HEScheduler.cc22
-rw-r--r--runtime/onert/core/src/compiler/HEScheduler.h8
-rw-r--r--runtime/onert/core/src/compiler/HEScheduler.test.cc6
-rw-r--r--runtime/onert/core/src/compiler/Linear.cc6
-rw-r--r--runtime/onert/core/src/compiler/Linear.h6
-rw-r--r--runtime/onert/core/src/compiler/LoweredGraph.cc22
-rw-r--r--runtime/onert/core/src/compiler/ManualScheduler.cc6
-rw-r--r--runtime/onert/core/src/compiler/MultiModelCompiler.cc46
-rw-r--r--runtime/onert/core/src/compiler/MultiModelCompiler.h6
-rw-r--r--runtime/onert/core/src/compiler/ShapeValidator.cc2
-rw-r--r--runtime/onert/core/src/compiler/StaticShapeInferer.cc36
-rw-r--r--runtime/onert/core/src/compiler/pass/ConstantInsertionPass.cc4
-rw-r--r--runtime/onert/core/src/compiler/pass/ConstantInsertionPass.h2
-rw-r--r--runtime/onert/core/src/compiler/pass/ConstantLoweringPass.cc4
-rw-r--r--runtime/onert/core/src/compiler/pass/ConstantLoweringPass.h2
-rw-r--r--runtime/onert/core/src/compiler/pass/ConstantOutputPass.cc2
-rw-r--r--runtime/onert/core/src/compiler/pass/IPass.h41
-rw-r--r--runtime/onert/core/src/compiler/pass/LoweredOperandPass.h6
-rw-r--r--runtime/onert/core/src/compiler/pass/LoweredOperationPass.h8
-rw-r--r--runtime/onert/core/src/compiler/pass/OperationPass.cc4
-rw-r--r--runtime/onert/core/src/compiler/pass/OperationPass.h4
-rw-r--r--runtime/onert/core/src/compiler/pass/Pass.h4
-rw-r--r--runtime/onert/core/src/compiler/pass/PassRunner.cc2
-rw-r--r--runtime/onert/core/src/compiler/pass/PassRunner.h6
-rw-r--r--runtime/onert/core/src/compiler/pass/PermutationEliminationPass.cc9
-rw-r--r--runtime/onert/core/src/compiler/pass/PermutationEliminationPass.h2
-rw-r--r--runtime/onert/core/src/compiler/pass/PermutationInsertionPass.cc6
-rw-r--r--runtime/onert/core/src/compiler/pass/PermutationOperationPass.cc2
-rw-r--r--runtime/onert/core/src/compiler/pass/PermutationOperationPass.h2
-rw-r--r--runtime/onert/core/src/compiler/pass/UnusedOperandEliminationPass.cc6
-rw-r--r--runtime/onert/core/src/compiler/train/LoweredTrainableGraph.cc285
-rw-r--r--runtime/onert/core/src/compiler/train/StaticDerivativeShapeInferer.cc150
-rw-r--r--runtime/onert/core/src/compiler/train/StaticDerivativeShapeInferer.h80
-rw-r--r--runtime/onert/core/src/compiler/train/TensorRegistries.h105
-rw-r--r--runtime/onert/core/src/compiler/train/TrainableOperationConverter.cc86
-rw-r--r--runtime/onert/core/src/compiler/train/TrainableOperationConverter.h57
-rw-r--r--runtime/onert/core/src/compiler/train/TrainingCompiler.cc299
-rw-r--r--runtime/onert/core/src/compiler/train/TrainingCompiler.h83
-rw-r--r--runtime/onert/core/src/compiler/train/UntrainableOperationConverter.cc53
-rw-r--r--runtime/onert/core/src/compiler/train/UntrainableOperationConverter.h52
-rw-r--r--runtime/onert/core/src/compiler/train/pass/LossInsertionPass.cc77
-rw-r--r--runtime/onert/core/src/compiler/train/pass/LossInsertionPass.h55
-rw-r--r--runtime/onert/core/src/compiler/train/pass/Pass.h64
-rw-r--r--runtime/onert/core/src/dumper/dot/DotBuilder.cc4
-rw-r--r--runtime/onert/core/src/dumper/dot/DotDumper.cc15
-rw-r--r--runtime/onert/core/src/dumper/dot/DotDumper.h4
-rw-r--r--runtime/onert/core/src/dumper/dot/OperationNode.cc2
-rw-r--r--runtime/onert/core/src/dumper/dot/OperationNode.h4
-rw-r--r--runtime/onert/core/src/dumper/h5/Dumper.cc34
-rw-r--r--runtime/onert/core/src/dumper/h5/Dumper.h51
-rw-r--r--runtime/onert/core/src/dumper/h5/MinMaxDumper.cc75
-rw-r--r--runtime/onert/core/src/dumper/h5/MinMaxDumper.h70
-rw-r--r--runtime/onert/core/src/dumper/text/GraphDumper.cc28
-rw-r--r--runtime/onert/core/src/dumper/text/GraphDumper.h15
-rw-r--r--runtime/onert/core/src/exec/DataflowExecutor.cc10
-rw-r--r--runtime/onert/core/src/exec/DynamicShapeInferer.cc8
-rw-r--r--runtime/onert/core/src/exec/ExecTime.test.cc2
-rw-r--r--runtime/onert/core/src/exec/Execution.cc42
-rw-r--r--runtime/onert/core/src/exec/ExecutionObservers.cc2
-rw-r--r--runtime/onert/core/src/exec/ExecutionObservers.h2
-rw-r--r--runtime/onert/core/src/exec/ExecutorBase.cc2
-rw-r--r--runtime/onert/core/src/exec/ExecutorBase.h1
-rw-r--r--runtime/onert/core/src/exec/Executors.cc2
-rw-r--r--runtime/onert/core/src/exec/FunctionSequence.cc1
-rw-r--r--runtime/onert/core/src/exec/LinearExecutor.h2
-rw-r--r--runtime/onert/core/src/exec/MinMaxRecorder.cc112
-rw-r--r--runtime/onert/core/src/exec/MinMaxRecorder.h56
-rw-r--r--runtime/onert/core/src/exec/ParallelScheduler.cc2
-rw-r--r--runtime/onert/core/src/exec/train/TrainableExecutor.cc204
-rw-r--r--runtime/onert/core/src/exec/train/TrainableExecutor.h109
-rw-r--r--runtime/onert/core/src/exec/train/TrainableExecutors.cc89
-rw-r--r--runtime/onert/core/src/exec/train/TrainableExecutors.h92
-rw-r--r--runtime/onert/core/src/exec/train/TrainableFnSequence.cc67
-rw-r--r--runtime/onert/core/src/exec/train/optimizer/OptimizerCode.cc42
-rw-r--r--runtime/onert/core/src/exec/train/optimizer/OptimizerHelpers.h47
-rw-r--r--runtime/onert/core/src/exec/train/optimizer/SGD.cc66
-rw-r--r--runtime/onert/core/src/ir/Graph.cc59
-rw-r--r--runtime/onert/core/src/ir/LayoutSet.cc8
-rw-r--r--runtime/onert/core/src/ir/LayoutSet.h1
-rw-r--r--runtime/onert/core/src/ir/OperandIndexSequence.cc9
-rw-r--r--runtime/onert/core/src/ir/OperationCloner.cc2
-rw-r--r--runtime/onert/core/src/ir/OperationCloner.h2
-rw-r--r--runtime/onert/core/src/ir/OperationDumper.cc8
-rw-r--r--runtime/onert/core/src/ir/OperationDumper.h1
-rw-r--r--runtime/onert/core/src/ir/OperationValidator.cc6
-rw-r--r--runtime/onert/core/src/ir/Operations.cc2
-rw-r--r--runtime/onert/core/src/ir/operation/Loss.cc52
-rw-r--r--runtime/onert/core/src/ir/train/TrainableGraph.cc145
-rw-r--r--runtime/onert/core/src/ir/train/operation/Conv2D.cc49
-rw-r--r--runtime/onert/core/src/ir/train/operation/ElementwiseActivation.cc49
-rw-r--r--runtime/onert/core/src/ir/train/operation/FullyConnected.cc49
-rw-r--r--runtime/onert/core/src/ir/train/operation/Loss.cc48
-rw-r--r--runtime/onert/core/src/ir/train/operation/Permute.cc50
-rw-r--r--runtime/onert/core/src/ir/train/operation/Pool2D.cc49
-rw-r--r--runtime/onert/core/src/ir/train/operation/Reshape.cc49
-rw-r--r--runtime/onert/core/src/ir/train/operation/Softmax.cc49
-rw-r--r--runtime/onert/core/src/ir/verifier/Verifier.cc16
-rw-r--r--runtime/onert/core/src/odc/QuantizeManager.cc50
-rw-r--r--runtime/onert/core/src/odc/QuantizeManager.test.cc36
-rw-r--r--runtime/onert/core/src/odc/QuantizerLoader.cc104
-rw-r--r--runtime/onert/core/src/odc/QuantizerLoader.h89
-rw-r--r--runtime/onert/core/src/odc/QuantizerLoader.test.cc63
-rw-r--r--runtime/onert/core/src/util/MDTableEventWriter.cc4
-rw-r--r--runtime/onert/frontend/base_loader/include/base_loader.h39
-rw-r--r--runtime/onert/frontend/circle_schema/include/circle_schema_generated.h1046
-rw-r--r--runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksModel.cc4
-rw-r--r--runtime/onert/frontend/tflite/src/tflite_schema_generated.h569
-rw-r--r--runtime/onert/frontend/tflite/tflite_schema.fbs237
-rw-r--r--runtime/onert/odc/CMakeLists.txt39
-rw-r--r--runtime/onert/odc/Quantizer.cc83
-rw-r--r--runtime/onert/odc/Quantizer.h39
-rw-r--r--runtime/onert/odc/Quantizer.test.cc42
-rw-r--r--runtime/service/npud/backend/trix/TrixBackend.cc4
-rw-r--r--runtime/service/npud/core/Backend.h1
-rw-r--r--tests/nnfw_api/src/CircleGen.cc2
-rw-r--r--tests/nnfw_api/src/one_op_tests/Conv2D.test.cc51
-rw-r--r--tests/nnfw_api/src/one_op_tests/DepthwiseConv2D.test.cc65
-rw-r--r--tests/tools/onert_run/src/args.cc4
-rw-r--r--tests/tools/onert_run/src/args.h4
-rw-r--r--tests/tools/onert_run/src/onert_run.cc59
-rw-r--r--tests/tools/onert_train/CMakeLists.txt60
-rw-r--r--tests/tools/onert_train/README.md13
-rw-r--r--tests/tools/onert_train/src/allocation.h46
-rw-r--r--tests/tools/onert_train/src/args.cc291
-rw-r--r--tests/tools/onert_train/src/args.h92
-rw-r--r--tests/tools/onert_train/src/formatter.h47
-rw-r--r--tests/tools/onert_train/src/h5formatter.cc258
-rw-r--r--tests/tools/onert_train/src/h5formatter.h41
-rw-r--r--tests/tools/onert_train/src/measure.h90
-rw-r--r--tests/tools/onert_train/src/nnfw_util.cc49
-rw-r--r--tests/tools/onert_train/src/nnfw_util.h37
-rw-r--r--tests/tools/onert_train/src/onert_train.cc277
-rw-r--r--tests/tools/onert_train/src/randomgen.cc77
-rw-r--r--tests/tools/onert_train/src/randomgen.h40
-rw-r--r--tests/tools/onert_train/src/rawdataloader.cc77
-rw-r--r--tests/tools/onert_train/src/rawdataloader.h51
-rw-r--r--tests/tools/onert_train/src/rawformatter.cc97
-rw-r--r--tests/tools/onert_train/src/rawformatter.h40
-rw-r--r--tests/tools/onert_train/src/types.h (renamed from onert-micro/luci-interpreter/pal/mcu/PALFill.h)16
-rw-r--r--tests/tools/onert_train/test/rawdataloader.test.cc224
-rw-r--r--tools/cross/aarch64/sources.list.jammy11
-rw-r--r--tools/cross/aarch64/sources.list.xenial11
-rwxr-xr-xtools/cross/armel/tizen-build-rootfs.sh43
-rwxr-xr-xtools/cross/armel/tizen-fetch.sh169
-rw-r--r--tools/cross/armel/tizen.patch18
-rwxr-xr-xtools/cross/install_rootfs.sh29
-rw-r--r--tools/generate_datafile/tf_dataset_converter/README.md66
-rw-r--r--tools/generate_datafile/tf_dataset_converter/argparser.py54
-rw-r--r--tools/generate_datafile/tf_dataset_converter/datasets.py80
-rw-r--r--tools/generate_datafile/tf_dataset_converter/main.py98
-rw-r--r--tools/generate_datafile/tf_dataset_converter/requirements.txt8
1445 files changed, 103502 insertions, 25491 deletions
diff --git a/.ahub/sam/exclude.txt b/.ahub/sam/exclude.txt
index f16f84f3c..3c2b71f06 100644
--- a/.ahub/sam/exclude.txt
+++ b/.ahub/sam/exclude.txt
@@ -47,3 +47,6 @@
# Downloaded externals
/ONE/externals
+
+# Intermediate code for runtime build (refer nnfw.spec file's nncc_workspace)
+/ONE/build/nncc/
diff --git a/.ahub/tcchecker-tca/config.yaml b/.ahub/tcchecker-tca/config.yaml
index 154fbf92a..12fbabefd 100644
--- a/.ahub/tcchecker-tca/config.yaml
+++ b/.ahub/tcchecker-tca/config.yaml
@@ -118,7 +118,7 @@ test:
- /compiler/luci-eval-driver
- /compiler/luci-pass-value-test
- /compiler/luci-value-test
- - /compiler/mio-circle04
+ - /compiler/mio-circle05
- /compiler/mio-tflite
- /compiler/mio-tflite260
- /compiler/oops
@@ -546,3 +546,89 @@ test:
positiveTestCase:
- condition:
- inverse: negativeTestCase
+ - name: onert-micro
+ testCaseLanguage: CPP
+ testFW: GTEST
+ testCaseFolder:
+ - /onert-micro
+
+ testFile:
+ - extension: test.cpp
+ any: true
+ - extension: test.cc
+ any: true
+ - excludes :
+ - Greater.test.cpp
+ - LeakyRelu.test.cpp
+ - Dequantize.test.cpp
+ - L2Normalize.test.cpp
+ - OneHot.test.cpp
+ - BatchToSpaceND.test.cpp
+ - BatchMatMul.test.cpp
+ - SpaceToBatchND.test.cpp
+ - LocalResponseNormalization.test.cpp
+ - LessEqual.test.cpp
+ - Minimum.test.cpp
+ - Relu6.test.cpp
+ - ResizeBilinear.test.cpp
+ - SquaredDifference.test.cpp
+ - SpaceToDepth.test.cpp
+ - SVDF.test.cpp
+ - Neg.test.cpp
+ - InstanceNorm.test.cpp
+ - MirrorPad.test.cpp
+ - Quantize.test.cpp
+ - ResizeNearestNeighbor.test.cpp
+ - LogicalNot.test.cpp
+ - Elu.test.cpp
+ - If.test.cpp
+ - ReverseV2.test.cpp
+ - Equal.test.cpp
+ - FloorDiv.test.cpp
+ - Rsqrt.test.cpp
+ - L2Pool2D.test.cpp
+ - PRelu.test.cpp
+ - TransposeConv.test.cpp
+ - ArgMax.test.cpp
+ - LogicalOr.test.cpp
+ - Div.test.cpp
+ - LogicalAnd.test.cpp
+ - Square.test.cpp
+ - AveragePool2D.test.cpp
+ - Pow.test.cpp
+ - Softmax.test.cpp
+ - NotEqual.test.cpp
+ - Cast.test.cpp
+ - Floor.test.cpp
+ - Exp.test.cpp
+ - GreaterEqual.test.cpp
+ - Maximum.test.cpp
+ - Mean.test.cpp
+ - PadV2.test.cpp
+ - Squeeze.test.cpp
+ - Pad.test.cpp
+ - DepthwiseConv2D.test.cpp
+ - Sqrt.test.cpp
+ - Relu.test.cpp
+ - LogSoftmax.test.cpp
+ - DepthToSpace.test.cpp
+ - Unpack.test.cpp
+ testCase:
+ - condition:
+ - functionName:
+ starts:
+ - TEST
+ - TYPED_TEST
+ - excludes :
+ - Verifier.dag_checker
+ negativeTestCase:
+ - condition:
+ - testName:
+ ends:
+ - _NEG
+
+ positiveTestCase:
+ - condition:
+ - testName:
+ ends:
+ - _P
diff --git a/.github/workflows/run-onert-micro-unit-tests.yml b/.github/workflows/run-onert-micro-unit-tests.yml
new file mode 100644
index 000000000..8b27e638b
--- /dev/null
+++ b/.github/workflows/run-onert-micro-unit-tests.yml
@@ -0,0 +1,47 @@
+name: Run onert-micro Unit tests
+
+on:
+ pull_request:
+ branches:
+ - master
+ - release/*
+ types:
+ - opened
+ - synchronize
+ - reopened
+ - ready_for_review
+ paths:
+ - 'onert-micro/**'
+ - '.github/workflows/run-onert-micro-unit-tests.yml'
+
+defaults:
+ run:
+ shell: bash
+
+jobs:
+ run-onert-micro-unit-tests:
+ name: Run onert-micro Unit tests
+ runs-on: ubuntu-20.04
+ # Skip on draft, check on draft -> ready
+ if: github.event.pull_request.draft == false
+
+ steps:
+ - name: Install Arm GNU Toolchain (arm-none-eabi-gcc)
+ uses: carlosperate/arm-none-eabi-gcc-action@v1
+ with:
+ release: '12.2.Rel1' # <-- The compiler release to use
+ - name: Checkout
+ uses: actions/checkout@v3
+ with:
+ # Checkout PR head commit
+ # Checkout Action use merge commit as default
+ ref: ${{ github.event.pull_request.head.sha }}
+ # Fetch all history and branch (default: 1)
+ fetch-depth: 0
+ - name: Build and Run Tests
+ run: |
+ mkdir build
+ cd build
+ cmake ../infra/onert-micro/ -DENABLE_ONERT_MICRO_TEST=1 -DENABLE_TEST=1
+ make -j$(nproc) luci_interpreter_kernels_micro_test
+ ./onert-micro/eval-driver/luci-interpreter/src/kernels/luci_interpreter_kernels_micro_test
diff --git a/Makefile.template b/Makefile.template
index 2e5d0bd02..7621a2f7a 100644
--- a/Makefile.template
+++ b/Makefile.template
@@ -96,6 +96,12 @@ TIMESTAMP_INSTALL=$(WORKSPACE)/INSTALL
export NNFW_WORKSPACE=$(WORKSPACE)
###
+### Common environment variable for compiler module
+###
+NNCC_FOLDER=Product/$(WORKFOLDER)/nncc
+export NNCC_WORKSPACE=$(NNCC_FOLDER)
+
+###
### Default target
###
all: install
@@ -103,6 +109,8 @@ all: install
###
### Command (public)
###
+prepare-nncc: prepare_nncc_internal
+
configure: configure_internal
build: build_internal
@@ -135,6 +143,21 @@ create_acl_tar: acl_tar_internal
$(WORKSPACE):
mkdir -p $@
+prepare_nncc_internal: $(WORKSPACE)
+ifneq ($(CROSS_BUILD),1)
+ ./nncc configure -DBUILD_GTEST=OFF -DENABLE_TEST=OFF -DEXTERNALS_BUILD_THREADS=$(NPROCS) -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) \
+ -DCMAKE_INSTALL_PREFIX=$(OVERLAY_FOLDER) \
+ -DBUILD_WHITELIST="luci;foder;pepper-csv2vec;loco;locop;logo;logo-core;mio-circle06;luci-compute;oops;hermes;hermes-std;angkor;pp;pepper-strcast;pepper-str"
+ ./nncc build -j$(NPROCS)
+ cmake --install $(NNCC_FOLDER)
+# install angkor TensorIndex and oops InternalExn header (TODO: Remove this)
+ @mkdir -p ${OVERLAY_FOLDER}/include/nncc/core/ADT/tensor
+ @mkdir -p ${OVERLAY_FOLDER}/include/oops
+ @cp compiler/angkor/include/nncc/core/ADT/tensor/Index.h ${OVERLAY_FOLDER}/include/nncc/core/ADT/tensor
+ @cp compiler/oops/include/oops/InternalExn.h ${OVERLAY_FOLDER}/include/oops
+endif
+ @echo "Done prepare-nncc"
+
configure_internal: $(WORKSPACE)
ifneq ($(DEBIAN_BUILD),)
test -d externals || mkdir -p externals
@@ -165,9 +188,14 @@ acl_tar_internal: configure_internal
install_acl_internal:
# Workaround to install acl for test (ignore error when there is no file to copy)
- cp $(OVERLAY_FOLDER)/lib/libarm_compute*.so $(INSTALL_ALIAS)/lib || true
+ @cp $(OVERLAY_FOLDER)/lib/libarm_compute*.so $(INSTALL_ALIAS)/lib 2>/dev/null || true
+
+install_luci_internal:
+ @mkdir -p $(INSTALL_ALIAS)/lib/nnfw/odc
+ @cp $(OVERLAY_FOLDER)/lib/libluci*.so $(INSTALL_ALIAS)/lib/nnfw/odc 2>/dev/null || true
+ @cp $(OVERLAY_FOLDER)/lib/libloco*.so $(INSTALL_ALIAS)/lib/nnfw/odc 2>/dev/null || true
-install_all_internal: install_internal install_acl_internal
+install_all_internal: install_internal install_acl_internal install_luci_internal
test_suite_internal: install_all_internal
@echo "packaging test suite"
diff --git a/compiler/CMakeLists.txt b/compiler/CMakeLists.txt
index 2588cf05d..ef13df857 100644
--- a/compiler/CMakeLists.txt
+++ b/compiler/CMakeLists.txt
@@ -12,8 +12,8 @@ else()
message(STATUS "WARNING: lsb_release not found")
endif()
-if(${ONE_UBUNTU_CODENAME} STREQUAL "jammy")
- set(ONE_UBUNTU_CODENAME_JAMMY TRUE)
+if(${ONE_UBUNTU_CODENAME} STREQUAL "bionic")
+ set(ONE_UBUNTU_CODENAME_BIONIC TRUE)
endif()
# TODO Validate the argument of "requires"
diff --git a/compiler/arser/CMakeLists.txt b/compiler/arser/CMakeLists.txt
index 7eda21564..b937ff6ad 100644
--- a/compiler/arser/CMakeLists.txt
+++ b/compiler/arser/CMakeLists.txt
@@ -2,7 +2,7 @@ add_library(arser INTERFACE)
# It specifies INTERFACE so that future targets linked with arser library will inherit its include directory.
# It means that a developer who want to link arser just need to add one line.
-# target_link_library(another-users-target arser)
+# target_link_library(another-users-target arser)
target_include_directories(arser INTERFACE include/)
target_link_libraries(arser INTERFACE nncc_coverage)
diff --git a/compiler/circle-eval-diff/src/InputDataLoader.cpp b/compiler/circle-eval-diff/src/InputDataLoader.cpp
index f15b2ba91..7b491a37a 100644
--- a/compiler/circle-eval-diff/src/InputDataLoader.cpp
+++ b/compiler/circle-eval-diff/src/InputDataLoader.cpp
@@ -126,17 +126,19 @@ InputDataLoader::Data HDF5Loader::get(uint32_t data_idx) const
data.at(input_idx) = *createEmptyTensor(input_node).get();
auto input_buffer = data.at(input_idx).buffer();
+ const auto input_buffer_bytes = data.at(input_idx).byte_size();
+
try
{
if (_hdf5->isRawData())
{
- _hdf5->readTensor(data_idx, input_idx, input_buffer);
+ _hdf5->readTensor(data_idx, input_idx, input_buffer, input_buffer_bytes);
}
else
{
DataType dtype;
Shape shape;
- _hdf5->readTensor(data_idx, input_idx, &dtype, &shape, input_buffer);
+ _hdf5->readTensor(data_idx, input_idx, &dtype, &shape, input_buffer, input_buffer_bytes);
// Check the type and the shape of the input data is valid
verifyTypeShape(input_node, dtype, shape);
@@ -164,7 +166,7 @@ DirectoryLoader::DirectoryLoader(const std::string &dir_path,
struct dirent *entry = nullptr;
const auto input_total_bytes = getTotalByteSizeOf(input_nodes);
- while (entry = readdir(dir))
+ while ((entry = readdir(dir)))
{
// Skip if the entry is not a regular file
if (entry->d_type != DT_REG)
diff --git a/compiler/circle-inspect/CMakeLists.txt b/compiler/circle-inspect/CMakeLists.txt
index 10d26d191..8edfde483 100644
--- a/compiler/circle-inspect/CMakeLists.txt
+++ b/compiler/circle-inspect/CMakeLists.txt
@@ -1,6 +1,6 @@
-if(NOT TARGET mio_circle04)
+if(NOT TARGET mio_circle06)
return()
-endif(NOT TARGET mio_circle04)
+endif(NOT TARGET mio_circle06)
set(DRIVER "driver/Driver.cpp")
@@ -10,6 +10,6 @@ add_executable(circle-inspect ${DRIVER} ${SOURCES})
target_include_directories(circle-inspect PRIVATE src)
target_link_libraries(circle-inspect arser)
target_link_libraries(circle-inspect foder)
-target_link_libraries(circle-inspect mio_circle04)
-target_link_libraries(circle-inspect mio_circle04_helper)
+target_link_libraries(circle-inspect mio_circle06)
+target_link_libraries(circle-inspect mio_circle06_helper)
target_link_libraries(circle-inspect safemain)
diff --git a/compiler/circle-inspect/requires.cmake b/compiler/circle-inspect/requires.cmake
index 183dfe227..b3a2638ef 100644
--- a/compiler/circle-inspect/requires.cmake
+++ b/compiler/circle-inspect/requires.cmake
@@ -1,4 +1,4 @@
require("arser")
require("foder")
-require("mio-circle04")
+require("mio-circle06")
require("safemain")
diff --git a/compiler/circle-interpreter-test/CMakeLists.txt b/compiler/circle-interpreter-test/CMakeLists.txt
index 50cd0c64b..fbb0fcd45 100644
--- a/compiler/circle-interpreter-test/CMakeLists.txt
+++ b/compiler/circle-interpreter-test/CMakeLists.txt
@@ -11,7 +11,17 @@ nnas_find_package(GTest REQUIRED)
file(GLOB_RECURSE TESTS "src/*.test.cpp")
GTest_AddTest(circle-interpreter-test ${TESTS})
-set_tests_properties(circle-interpreter-test
- PROPERTIES
- ENVIRONMENT "ARTIFACTS_PATH=${ARTIFACTS_PATH};CIRCLE_INTERPRETER_PATH=${CIRCLE_INTERPRETER_PATH}"
- )
+# circle-interpreter-test uses input data generated during luci_value_test
+if(NOT CMAKE_CROSSCOMPILING)
+ set_tests_properties(circle-interpreter-test
+ PROPERTIES
+ DEPENDS luci_value_test
+ ENVIRONMENT "ARTIFACTS_PATH=${ARTIFACTS_PATH};CIRCLE_INTERPRETER_PATH=${CIRCLE_INTERPRETER_PATH}"
+ )
+else(NOT CMAKE_CROSSCOMPILING)
+ set_tests_properties(circle-interpreter-test
+ PROPERTIES
+ DEPENDS luci_value_cross_test
+ ENVIRONMENT "ARTIFACTS_PATH=${ARTIFACTS_PATH};CIRCLE_INTERPRETER_PATH=${CIRCLE_INTERPRETER_PATH}"
+ )
+endif(NOT CMAKE_CROSSCOMPILING)
diff --git a/compiler/circle-interpreter-test/requires.cmake b/compiler/circle-interpreter-test/requires.cmake
index 8d8585b47..5ca5749ca 100644
--- a/compiler/circle-interpreter-test/requires.cmake
+++ b/compiler/circle-interpreter-test/requires.cmake
@@ -1,2 +1,3 @@
require("common-artifacts")
require("circle-interpreter")
+require("luci-value-test")
diff --git a/compiler/circle-mpqsolver/CMakeLists.txt b/compiler/circle-mpqsolver/CMakeLists.txt
index 25e318e62..9af9fc2a3 100644
--- a/compiler/circle-mpqsolver/CMakeLists.txt
+++ b/compiler/circle-mpqsolver/CMakeLists.txt
@@ -1,13 +1,20 @@
+nnas_find_package(Jsoncpp)
+if(NOT Jsoncpp_FOUND)
+ message(STATUS "Build circle-mpqsolver: FAILED (missing jsoncpp)")
+ return()
+endif(NOT Jsoncpp_FOUND)
+
file(GLOB_RECURSE SOURCES "src/*.cpp")
file(GLOB_RECURSE TESTS "src/*.test.cpp")
list(REMOVE_ITEM SOURCES ${TESTS})
add_executable(circle-mpqsolver "${SOURCES}")
target_include_directories(circle-mpqsolver PRIVATE src)
+target_include_directories(circle-mpqsolver PRIVATE ${Jsoncpp_INCLUDE_DIRS})
+target_link_libraries(circle-mpqsolver ${Jsoncpp_STATIC_LIB})
target_link_libraries(circle-mpqsolver arser)
target_link_libraries(circle-mpqsolver vconone)
target_link_libraries(circle-mpqsolver safemain)
-target_link_libraries(circle-mpqsolver luci_lang)
target_link_libraries(circle-mpqsolver luci_service)
target_link_libraries(circle-mpqsolver luci_pass)
target_link_libraries(circle-mpqsolver luci_interpreter)
@@ -27,11 +34,15 @@ endif(NOT ENABLE_TEST)
# Instead, we use TEST_SOURCES to specify sources uesd for tests.
set(TEST_SOURCES
"src/bisection/DepthParameterizer.cpp"
- "src/bisection/Quantizer.cpp"
- "src/bisection/ErrorApproximator.cpp")
+ "src/core/Quantizer.cpp"
+ "src/bisection/VISQErrorApproximator.cpp"
+ "src/core/ErrorMetric.cpp"
+)
nnas_find_package(GTest REQUIRED)
GTest_AddTest(circle_mpqsolver_test ${TESTS} ${TEST_SOURCES})
-target_link_libraries(circle_mpqsolver_test luci_lang)
+target_include_directories(circle_mpqsolver_test PRIVATE src)
+target_include_directories(circle_mpqsolver_test PRIVATE ${Jsoncpp_INCLUDE_DIRS})
+target_link_libraries(circle_mpqsolver_test ${Jsoncpp_STATIC_LIB})
target_link_libraries(circle_mpqsolver_test luci_service)
target_link_libraries(circle_mpqsolver_test luci_pass)
diff --git a/compiler/circle-mpqsolver/README.md b/compiler/circle-mpqsolver/README.md
index 9f4c2e74f..aa66e28a7 100644
--- a/compiler/circle-mpqsolver/README.md
+++ b/compiler/circle-mpqsolver/README.md
@@ -39,6 +39,8 @@ Run _circle-mpqsolver_ with the following arguments.
--qerror_ratio: Target quantization error ratio. It should be in [0, 1]. 0 indicates qerror of full int16 model, 1 indicates qerror of full uint8 model. The lower `qerror_ratio` indicates the more accurate solution.
--bisection _mode_: input nodes should be at Q16 precision ['auto', 'true', 'false']
+--visq_file: .visq.json file to be used in 'auto' mode
+--save_intermediate: path to the directory where all intermediate results will be saved
```
$ ./circle-mpqsolver
@@ -47,6 +49,8 @@ $ ./circle-mpqsolver
--output_model <output_model_pat>
--qerror_ratio <optional value for reproducing target _qerror_ default is 0.5>
--bisection <whether input nodes should be quantized into Q16 default is 'auto'>
+ --visq_file <*.visq.json file with quantization errors>
+ --save_intermediate <intermediate_results_path>
```
For example:
diff --git a/compiler/circle-mpqsolver/src/CircleMPQSolver.cpp b/compiler/circle-mpqsolver/src/CircleMPQSolver.cpp
index 23e8fd4ce..12981be40 100644
--- a/compiler/circle-mpqsolver/src/CircleMPQSolver.cpp
+++ b/compiler/circle-mpqsolver/src/CircleMPQSolver.cpp
@@ -18,13 +18,12 @@
#include <vconone/vconone.h>
#include <luci/CircleExporter.h>
#include <luci/CircleFileExpContract.h>
-#include <luci/Log.h>
#include "bisection/BisectionSolver.h"
+#include <core/SolverOutput.h>
#include <iostream>
#include <iomanip>
-#include <chrono>
void print_version(void)
{
@@ -32,11 +31,23 @@ void print_version(void)
std::cout << vconone::get_copyright() << std::endl;
}
-int entry(int argc, char **argv)
+int handleAutoAlgorithm(arser::Arser &arser, mpqsolver::bisection::BisectionSolver &solver)
{
- LOGGER(l);
+ solver.algorithm(mpqsolver::bisection::BisectionSolver::Algorithm::Auto);
+ auto data_path = arser.get<std::string>("--visq_file");
+ if (data_path.empty())
+ {
+ std::cerr << "ERROR: please provide visq_file for auto mode" << std::endl;
+ return false;
+ }
+ solver.setVisqPath(data_path);
+ return true;
+}
+int entry(int argc, char **argv)
+{
const std::string bisection_str = "--bisection";
+ const std::string save_intermediate_str = "--save_intermediate";
arser::Arser arser("circle-mpqsolver provides light-weight methods for finding a high-quality "
"mixed-precision model within a reasonable time.");
@@ -74,6 +85,17 @@ int entry(int argc, char **argv)
arser.add_argument("--output_model").required(true).help("Output quantized model");
+ arser.add_argument("--visq_file")
+ .type(arser::DataType::STR)
+ .default_value("")
+ .required(false)
+ .help("*.visq.json file with quantization errors");
+
+ arser.add_argument(save_intermediate_str)
+ .type(arser::DataType::STR)
+ .required(false)
+ .help("path to save intermediate results");
+
try
{
arser.parse(argc, argv);
@@ -104,7 +126,12 @@ int entry(int argc, char **argv)
std::cerr << "ERROR: quantization ratio must be in [0, 1]" << std::endl;
return EXIT_FAILURE;
}
- auto start = std::chrono::high_resolution_clock::now();
+
+ SolverOutput::get() << ">> Searching mixed precision configuration \n"
+ << "model:" << input_model_path << "\n"
+ << "dataset: " << data_path << "\n"
+ << "input dtype: " << input_dtype << "\n"
+ << "output dtype: " << output_dtype << "\n";
if (arser[bisection_str])
{
@@ -116,14 +143,20 @@ int entry(int argc, char **argv)
auto value = arser.get<std::string>(bisection_str);
if (value == "auto")
{
- solver.algorithm(BisectionSolver::Algorithm::Auto);
+ SolverOutput::get() << "algorithm: bisection (auto)\n";
+ if (!handleAutoAlgorithm(arser, solver))
+ {
+ return EXIT_FAILURE;
+ }
}
else if (value == "true")
{
+ SolverOutput::get() << "algorithm: bisection (Q16AtFront)";
solver.algorithm(BisectionSolver::Algorithm::ForceQ16Front);
}
else if (value == "false")
{
+ SolverOutput::get() << "algorithm: bisection (Q8AtFront)";
solver.algorithm(BisectionSolver::Algorithm::ForceQ16Back);
}
else
@@ -134,6 +167,18 @@ int entry(int argc, char **argv)
}
}
+ if (arser[save_intermediate_str])
+ {
+ auto data_path = arser.get<std::string>(save_intermediate_str);
+ if (!data_path.empty())
+ {
+ solver.set_save_intermediate(data_path);
+ }
+ }
+
+ SolverOutput::get() << "qerror metric: MAE\n"
+ << "target qerror ratio: " << qerror_ratio << "\n";
+
auto optimized = solver.run(input_model_path);
if (optimized == nullptr)
{
@@ -143,6 +188,7 @@ int entry(int argc, char **argv)
// save optimized
{
+ SolverOutput::get() << "Saving output model to " << output_model_path << "\n";
luci::CircleExporter exporter;
luci::CircleFileExpContract contract(optimized.get(), output_model_path);
if (!exporter.invoke(&contract))
@@ -159,10 +205,5 @@ int entry(int argc, char **argv)
return EXIT_FAILURE;
}
- auto duration = std::chrono::duration_cast<std::chrono::seconds>(
- std::chrono::high_resolution_clock::now() - start);
- VERBOSE(l, 0) << "Elapsed Time: " << std::setprecision(5) << duration.count() / 60.f
- << " minutes." << std::endl;
-
return EXIT_SUCCESS;
}
diff --git a/compiler/circle-mpqsolver/src/MPQSolver.cpp b/compiler/circle-mpqsolver/src/MPQSolver.cpp
index 02732eb4d..10cfbb65f 100644
--- a/compiler/circle-mpqsolver/src/MPQSolver.cpp
+++ b/compiler/circle-mpqsolver/src/MPQSolver.cpp
@@ -24,3 +24,8 @@ MPQSolver::MPQSolver(const std::string &input_data_path, float qerror_ratio,
_input_quantization(input_quantization), _output_quantization(output_quantization)
{
}
+
+void MPQSolver::set_save_intermediate(const std::string &save_path)
+{
+ _hooks = std::make_unique<core::DumpingHooks>(save_path);
+}
diff --git a/compiler/circle-mpqsolver/src/MPQSolver.h b/compiler/circle-mpqsolver/src/MPQSolver.h
index 7c018d0d8..6c5d25dad 100644
--- a/compiler/circle-mpqsolver/src/MPQSolver.h
+++ b/compiler/circle-mpqsolver/src/MPQSolver.h
@@ -17,7 +17,7 @@
#ifndef __MPQSOLVER_MPQSOLEVR_SOLVER_H__
#define __MPQSOLVER_MPQSOLEVR_SOLVER_H__
-#include <luci/IR/Module.h>
+#include <core/DumpingHooks.h>
#include <memory>
#include <string>
@@ -42,11 +42,17 @@ public:
*/
virtual std::unique_ptr<luci::Module> run(const std::string &module_path) = 0;
+ /**
+ * @brief set all intermediate artifacts to be saved
+ */
+ void set_save_intermediate(const std::string &save_path);
+
protected:
std::string _input_data_path;
std::string _input_quantization;
std::string _output_quantization;
float _qerror_ratio = 0.f; // quantization error ratio
+ std::unique_ptr<core::DumpingHooks> _hooks;
};
} // namespace mpqsolver
diff --git a/compiler/circle-mpqsolver/src/bisection/BisectionSolver.cpp b/compiler/circle-mpqsolver/src/bisection/BisectionSolver.cpp
index d5068021f..976dac550 100644
--- a/compiler/circle-mpqsolver/src/bisection/BisectionSolver.cpp
+++ b/compiler/circle-mpqsolver/src/bisection/BisectionSolver.cpp
@@ -16,11 +16,12 @@
#include "BisectionSolver.h"
#include "DepthParameterizer.h"
-#include "ErrorMetric.h"
-#include "ErrorApproximator.h"
+#include "VISQErrorApproximator.h"
+
+#include <core/ErrorMetric.h>
+#include <core/SolverOutput.h>
#include <luci/ImporterEx.h>
-#include <luci/Log.h>
#include <cmath>
#include <iostream>
@@ -30,15 +31,23 @@ using namespace mpqsolver::bisection;
namespace
{
-bool error_at_input_is_larger_than_at_output(const NodeDepthType &nodes_depth, float cut_depth)
+/**
+ * @brief Compare errors of two disjoint subsets of a model sliced by cut_depth
+ * @return True if the front part (< cut_depth) has larger errors than the rear part (>= cut_depth)
+ */
+bool front_has_higher_error(const NodeDepthType &nodes_depth, const std::string &visq_path,
+ float cut_depth)
{
- LOGGER(l);
+ SolverOutput::get() << "\n>> Running bisection(auto) algorithm\n";
+
+ VISQErrorApproximator approximator;
+ approximator.init(visq_path);
float error_at_input = 0;
float error_at_output = 0;
for (auto &iter : nodes_depth)
{
- float cur_error = approximate(iter.first);
+ float cur_error = approximator.approximate(iter.first->name());
if (iter.second < cut_depth)
{
error_at_input += cur_error;
@@ -49,16 +58,16 @@ bool error_at_input_is_larger_than_at_output(const NodeDepthType &nodes_depth, f
}
}
+ SolverOutput::get() << "Qerror of front half: " << error_at_input << "\n";
+ SolverOutput::get() << "Qerror of rear half: " << error_at_output << "\n";
if (error_at_input > error_at_output)
{
- VERBOSE(l, 0) << "Q16 will be set at input due to ";
+ SolverOutput::get() << "Front part will be Q16, while the rear will be Q8\n";
}
else
{
- VERBOSE(l, 0) << "Q8 will be set at input due to ";
+ SolverOutput::get() << "Front part will be Q8, while the rear will be Q16\n";
}
- VERBOSE(l, 0) << error_at_input << " error at input vs ";
- VERBOSE(l, 0) << error_at_output << " error at output." << std::endl;
return error_at_input > error_at_output;
}
@@ -83,11 +92,12 @@ BisectionSolver::BisectionSolver(const std::string &input_data_path, float qerro
const std::string &output_quantization)
: MPQSolver(input_data_path, qerror_ratio, input_quantization, output_quantization)
{
- _quantizer = std::make_unique<Quantizer>(_input_quantization, _output_quantization);
+ _quantizer = std::make_unique<core::Quantizer>(_input_quantization, _output_quantization);
}
-float BisectionSolver::evaluate(const DatasetEvaluator &evaluator, const std::string &flt_path,
- const std::string &def_quant, LayerParams &layers)
+float BisectionSolver::evaluate(const core::DatasetEvaluator &evaluator,
+ const std::string &flt_path, const std::string &def_quant,
+ core::LayerParams &layers)
{
auto model = read_module(flt_path);
// get fake quantized model for evaluation
@@ -101,10 +111,10 @@ float BisectionSolver::evaluate(const DatasetEvaluator &evaluator, const std::st
void BisectionSolver::algorithm(Algorithm algorithm) { _algorithm = algorithm; }
+void BisectionSolver::setVisqPath(const std::string &visq_path) { _visq_data_path = visq_path; }
+
std::unique_ptr<luci::Module> BisectionSolver::run(const std::string &module_path)
{
- LOGGER(l);
-
auto module = read_module(module_path);
float min_depth = 0.f;
@@ -117,17 +127,24 @@ std::unique_ptr<luci::Module> BisectionSolver::run(const std::string &module_pat
return nullptr;
}
- std::unique_ptr<MAEMetric> metric = std::make_unique<MAEMetric>();
- DatasetEvaluator evaluator(module.get(), _input_data_path, *metric.get());
+ SolverOutput::get() << "\n>> Computing baseline qerrors\n";
+
+ std::unique_ptr<core::MAEMetric> metric = std::make_unique<core::MAEMetric>();
+ core::DatasetEvaluator evaluator(module.get(), _input_data_path, *metric.get());
- LayerParams layer_params;
+ core::LayerParams layer_params;
float int16_qerror =
evaluate(evaluator, module_path, "int16" /* default quant_dtype */, layer_params);
- VERBOSE(l, 0) << "Full int16 model quantization error " << int16_qerror << std::endl;
+ SolverOutput::get() << "Full int16 model qerror: " << int16_qerror << "\n";
float uint8_qerror =
evaluate(evaluator, module_path, "uint8" /* default quant_dtype */, layer_params);
- VERBOSE(l, 0) << "Full uint8 model quantization error " << uint8_qerror << std::endl;
+ SolverOutput::get() << "Full uint8 model qerror: " << uint8_qerror << "\n";
+ _quantizer->set_hook(_hooks.get());
+ if (_hooks)
+ {
+ _hooks->on_begin_solver(module_path, uint8_qerror, int16_qerror);
+ }
if (int16_qerror > uint8_qerror)
{
@@ -135,7 +152,7 @@ std::unique_ptr<luci::Module> BisectionSolver::run(const std::string &module_pat
}
_qerror = int16_qerror + _qerror_ratio * std::fabs(uint8_qerror - int16_qerror);
- VERBOSE(l, 0) << "Target quantization error " << _qerror << std::endl;
+ SolverOutput::get() << "Target qerror: " << _qerror << "\n";
if (uint8_qerror <= _qerror)
{
@@ -149,7 +166,8 @@ std::unique_ptr<luci::Module> BisectionSolver::run(const std::string &module_pat
int last_depth = -1;
float best_depth = -1;
- LayerParams best_params;
+ float best_accuracy = -1;
+ core::LayerParams best_params;
if (module->size() != 1)
{
throw std::runtime_error("Unsupported module");
@@ -173,27 +191,40 @@ std::unique_ptr<luci::Module> BisectionSolver::run(const std::string &module_pat
{
case Algorithm::Auto:
int16_front =
- error_at_input_is_larger_than_at_output(nodes_depth, 0.5f * (max_depth + min_depth));
+ front_has_higher_error(nodes_depth, _visq_data_path, 0.5f * (max_depth + min_depth));
break;
case Algorithm::ForceQ16Front:
+ SolverOutput::get() << "Front part will be Q16, while the rear will be Q8\n";
int16_front = true;
break;
case Algorithm::ForceQ16Back:
- int16_front = true;
+ SolverOutput::get() << "Front part will be Q8, while the rear will be Q16\n";
+ int16_front = false;
break;
}
+ SolverOutput::get() << "\n";
+
while (true)
{
+ if (_hooks)
+ {
+ _hooks->on_begin_iteration();
+ }
+
int cut_depth = static_cast<int>(std::floor(0.5f * (min_depth + max_depth)));
if (last_depth == cut_depth)
{
break;
}
+
+ SolverOutput::get() << "Looking for the optimal configuration in [" << min_depth << " , "
+ << max_depth << "] depth segment\n";
+
last_depth = cut_depth;
- LayerParams layer_params;
+ core::LayerParams layer_params;
for (auto &node : active_nodes)
{
auto cur_node = loco::must_cast<luci::CircleNode *>(node);
@@ -207,7 +238,7 @@ std::unique_ptr<luci::Module> BisectionSolver::run(const std::string &module_pat
if ((depth <= cut_depth && int16_front) || (depth >= cut_depth && !int16_front))
{
- auto layer_param = std::make_shared<LayerParam>();
+ auto layer_param = std::make_shared<core::LayerParam>();
{
layer_param->name = cur_node->name();
layer_param->dtype = "int16";
@@ -219,21 +250,36 @@ std::unique_ptr<luci::Module> BisectionSolver::run(const std::string &module_pat
}
float cur_accuracy = evaluate(evaluator, module_path, "uint8", layer_params);
- VERBOSE(l, 0) << cut_depth << " : " << cur_accuracy << std::endl;
+
+ if (_hooks)
+ {
+ _hooks->on_end_iteration(layer_params, "uint8", cur_accuracy);
+ }
if (cur_accuracy < _qerror)
{
+ SolverOutput::get() << "Qerror at depth " << cut_depth << " is " << cur_accuracy
+ << " < target qerror (" << _qerror << ")\n";
int16_front ? (max_depth = cut_depth) : (min_depth = cut_depth);
best_params = layer_params;
best_depth = cut_depth;
+ best_accuracy = cur_accuracy;
}
else
{
+ SolverOutput::get() << "Qerror at depth " << cut_depth << " is " << cur_accuracy
+ << (cur_accuracy > _qerror ? " > " : " == ") << "target qerror ("
+ << _qerror << ")\n";
int16_front ? (min_depth = cut_depth) : (max_depth = cut_depth);
}
}
- VERBOSE(l, 0) << "Found the best configuration at " << best_depth << " depth." << std::endl;
+ if (_hooks)
+ {
+ _hooks->on_end_solver(best_params, "uint8", best_accuracy);
+ }
+
+ SolverOutput::get() << "Found the best configuration at depth " << best_depth << "\n";
if (!_quantizer->quantize(module.get(), "uint8", best_params))
{
std::cerr << "ERROR: Failed to quantize model" << std::endl;
diff --git a/compiler/circle-mpqsolver/src/bisection/BisectionSolver.h b/compiler/circle-mpqsolver/src/bisection/BisectionSolver.h
index 7ec2e6944..83851c0c8 100644
--- a/compiler/circle-mpqsolver/src/bisection/BisectionSolver.h
+++ b/compiler/circle-mpqsolver/src/bisection/BisectionSolver.h
@@ -17,8 +17,8 @@
#ifndef __MPQSOLVER_BISECTION_SOLVER_H__
#define __MPQSOLVER_BISECTION_SOLVER_H__
-#include "Quantizer.h"
-#include "Evaluator.h"
+#include <core/Quantizer.h>
+#include <core/Evaluator.h>
#include <MPQSolver.h>
#include <luci/IR/Module.h>
@@ -64,14 +64,22 @@ public:
*/
void algorithm(Algorithm algorithm);
+ /**
+ * @brief set visq_file path to be used in 'auto' mode
+ * @details this is used to handle which way (8 or 16bit) of
+ * splitting the neural network will be the best for accuracy.
+ */
+ void setVisqPath(const std::string &visq_path);
+
private:
- float evaluate(const DatasetEvaluator &evaluator, const std::string &module_path,
- const std::string &def_quant, LayerParams &layers);
+ float evaluate(const core::DatasetEvaluator &evaluator, const std::string &module_path,
+ const std::string &def_quant, core::LayerParams &layers);
private:
float _qerror = 0.f; // quantization error
Algorithm _algorithm = Algorithm::ForceQ16Front;
- std::unique_ptr<Quantizer> _quantizer;
+ std::unique_ptr<core::Quantizer> _quantizer;
+ std::string _visq_data_path;
};
} // namespace bisection
diff --git a/compiler/circle-mpqsolver/src/bisection/DepthParameterizer.test.cpp b/compiler/circle-mpqsolver/src/bisection/DepthParameterizer.test.cpp
index d3865e4ca..504032d6b 100644
--- a/compiler/circle-mpqsolver/src/bisection/DepthParameterizer.test.cpp
+++ b/compiler/circle-mpqsolver/src/bisection/DepthParameterizer.test.cpp
@@ -17,7 +17,7 @@
#include <gtest/gtest.h>
#include "DepthParameterizer.h"
-#include "TestHelper.h"
+#include <core/TestHelper.h>
#include <luci/IR/CircleNodes.h>
diff --git a/compiler/circle-mpqsolver/src/bisection/ErrorApproximator.cpp b/compiler/circle-mpqsolver/src/bisection/ErrorApproximator.cpp
deleted file mode 100644
index ebd725812..000000000
--- a/compiler/circle-mpqsolver/src/bisection/ErrorApproximator.cpp
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "ErrorApproximator.h"
-
-#include <cmath>
-#include <limits>
-#include <vector>
-#include <functional>
-#include <luci/IR/CircleNode.h>
-
-namespace
-{
-
-using namespace luci;
-using IterFunc = std::function<void(uint32_t *, loco::TensorShape &, int32_t)>;
-
-inline bool has_min_max(const CircleNode *node)
-{
- return node->quantparam() && !node->quantparam()->min.empty() && !node->quantparam()->max.empty();
-}
-
-inline uint32_t cal_offset(const loco::TensorShape &dimension, uint32_t *indices)
-{
- return indices[0] * dimension.dim(1).value() * dimension.dim(2).value() *
- dimension.dim(3).value() +
- indices[1] * dimension.dim(2).value() * dimension.dim(3).value() +
- indices[2] * dimension.dim(3).value() + indices[3];
-}
-
-uint32_t get_channel_dim_index(const CircleNode *node)
-{
- uint32_t index = 0;
- auto opcode = node->opcode();
- switch (opcode)
- {
- case CircleOpcode::CONV_2D:
- case CircleOpcode::TRANSPOSE_CONV:
- case CircleOpcode::FULLY_CONNECTED:
- index = 0;
- break;
- case CircleOpcode::DEPTHWISE_CONV_2D:
- index = 3;
- break;
- default:
- throw std::runtime_error("Failed to find channel index in " + node->name());
- }
-
- return index;
-}
-
-bool set_weight_dim(const CircleNode *node, const CircleConst *weights,
- loco::TensorShape &dimension)
-{
- auto opcode = node->opcode();
- switch (opcode)
- {
- case CircleOpcode::CONV_2D:
- case CircleOpcode::TRANSPOSE_CONV:
- case CircleOpcode::DEPTHWISE_CONV_2D:
- assert(node->rank() == 4);
- dimension.rank(node->rank());
- dimension.dim(0).set(weights->dim(0).value());
- dimension.dim(1).set(weights->dim(1).value());
- dimension.dim(2).set(weights->dim(2).value());
- dimension.dim(3).set(weights->dim(3).value());
- break;
- case CircleOpcode::FULLY_CONNECTED:
- assert(node->rank() == 2);
- dimension.rank(4);
- dimension.dim(0).set(weights->dim(0).value());
- dimension.dim(1).set(1); // Set FC layer like CONV
- dimension.dim(2).set(1);
- dimension.dim(3).set(weights->dim(1).value());
- break;
- default:
- return false;
- }
-
- return true;
-}
-
-loco::Node *get_weight(const CircleNode *node)
-{
- loco::Node *weight = nullptr;
- auto opcode = node->opcode();
- switch (opcode)
- {
- case CircleOpcode::CONV_2D:
- {
- auto conv = loco::must_cast<const CircleConv2D *>(node);
- weight = conv->filter();
- }
- break;
- case CircleOpcode::DEPTHWISE_CONV_2D:
- {
- auto dconv = loco::must_cast<const CircleDepthwiseConv2D *>(node);
- weight = dconv->filter();
- }
- break;
- case CircleOpcode::TRANSPOSE_CONV:
- {
- auto tconv = loco::must_cast<const CircleTransposeConv *>(node);
- weight = tconv->filter();
- }
- break;
- case CircleOpcode::FULLY_CONNECTED:
- {
- auto fc = loco::must_cast<const CircleFullyConnected *>(node);
- weight = fc->weights();
- }
- break;
- default:
- break;
- }
-
- return weight;
-}
-
-inline CircleConst *get_constant_weight(const CircleNode *node)
-{
- CircleConst *weight = dynamic_cast<CircleConst *>(get_weight(node));
- if (weight == nullptr)
- {
- throw std::runtime_error("Unsupported non-constant weights in convolution node " +
- node->name());
- }
-
- return weight;
-}
-
-void iterate_per_channel(const CircleNode *node, IterFunc func)
-{
- CircleConst *weight = get_constant_weight(node);
-
- loco::TensorShape dimension;
- set_weight_dim(node, weight, dimension);
- uint32_t indices[4] = {
- 0,
- };
-
- auto channel_dim_index = get_channel_dim_index(node);
-
- for (indices[0] = 0; indices[0] < dimension.dim(0).value(); indices[0]++)
- {
- for (indices[1] = 0; indices[1] < dimension.dim(1).value(); indices[1]++)
- {
- for (indices[2] = 0; indices[2] < dimension.dim(2).value(); indices[2]++)
- {
- for (indices[3] = 0; indices[3] < dimension.dim(3).value(); indices[3]++)
- {
- func(indices, dimension, channel_dim_index);
- }
- }
- }
- }
-}
-
-void cal_minmax_per_channel(const CircleNode *node, std::vector<float> &min,
- std::vector<float> &max)
-{
- CircleConst *weight = get_constant_weight(node);
-
- loco::TensorShape dimension;
- set_weight_dim(node, weight, dimension);
-
- auto channel_dim_index = get_channel_dim_index(node);
- auto size = dimension.dim(channel_dim_index).value();
-
- std::vector<bool> has_min_max_value(size, false);
- min.resize(size);
- max.resize(size);
-
- auto cal_minmax = [&](uint32_t *indices, loco::TensorShape &dimension,
- uint32_t channel_dim_index) {
- uint32_t channel_idx = indices[channel_dim_index];
- auto data = weight->at<loco::DataType::FLOAT32>(cal_offset(dimension, indices));
- if (has_min_max_value[channel_idx])
- {
- min[channel_idx] = data < min[channel_idx] ? data : min[channel_idx];
- max[channel_idx] = data > max[channel_idx] ? data : max[channel_idx];
- }
- else
- {
- min[channel_idx] = data;
- max[channel_idx] = data;
- has_min_max_value[channel_idx] = true;
- }
- };
-
- iterate_per_channel(node, cal_minmax);
-}
-
-bool get_shape(const CircleNode *circle_node, std::vector<uint32_t> &shape)
-{
- if (circle_node->shape_status() == ShapeStatus::VALID)
- {
- auto rank = circle_node->rank();
- if (rank != 4)
- return false;
-
- shape.resize(rank);
- for (uint32_t i = 0; i < rank; i++)
- {
- shape[i] = circle_node->dim(i).value();
- }
- return true;
- }
-
- return false;
-}
-
-/**
- * @brief get_additions_per_channel computes W * H * CIN * KW * KH.
- *
- * W, H - width/height of OFM; KW, KH - convolution kernel width/height;
- * CIN - number of channels in IFM (for depthwise its unity)
- * See
- * https://github.com/Samsung/ONE/pull/10170#discussion_r1065371638
- * for derivation.
- */
-uint32_t get_additions_per_channel(const CircleNode *node)
-{
- uint32_t adds_per_channel = 1;
- std::vector<uint32_t> ofm_shape;
- if (!get_shape(node, ofm_shape)) // [BATCH, W, H, channels_out]
- {
- throw std::runtime_error("Failed to find correct shape " + node->name());
- }
-
- adds_per_channel *= ofm_shape[1] * ofm_shape[2]; // adds_per_channel *= W * H
-
- auto weights = loco::must_cast<CircleNode *>(get_weight(node));
- {
- std::vector<uint32_t> w_shape;
- if (get_shape(weights, w_shape)) // [channels_out, k_x, k_y, channels_in]
- {
- adds_per_channel *= (w_shape[1] * w_shape[2]); // adds_per_channel *= k_x * k_y
- }
- if (node->opcode() != CircleOpcode::DEPTHWISE_CONV_2D)
- {
- // for not depthwise convolutions we need to scale it by CIN
- adds_per_channel *= w_shape[3]; // adds_per_channel *= c_in
- }
- }
-
- return adds_per_channel;
-}
-
-void get_min_max_ifm_values(const CircleNode *node, float &ci_min, float &ci_max)
-{
- auto preds = loco::preds(node);
- for (const auto &pred : preds)
- {
- auto parent_node = loco::must_cast<const luci::CircleNode *>(pred);
- if (has_min_max(parent_node))
- {
- auto quantparam = parent_node->quantparam();
- if (quantparam->min.size() > 0)
- {
- ci_min = quantparam->min[0];
- ci_max = quantparam->max[0];
- }
- }
- }
-}
-
-/**
- * @brief Return upper bound of quantization error for CONV, DCONV, TCONV.
- *
- * See
- * https://github.com/Samsung/ONE/pull/10170#discussion_r1065371638 for details.
- */
-float approximate_conv(const CircleNode *node)
-{
- float volume_W_A_err = 0.f;
- {
- // activation min-max values
- float ci_min = 0.f;
- float ci_max = 0.f;
- get_min_max_ifm_values(node, ci_min, ci_max);
-
- // channel-wise min, max
- std::vector<float> min_values;
- std::vector<float> max_values;
- cal_minmax_per_channel(node, min_values, max_values);
- assert(not min_values.empty());
- assert(not max_values.empty());
-
- // ranges = (max_values - min_values)
- std::vector<float> ranges;
- std::transform(max_values.begin(), max_values.end(), min_values.begin(),
- std::back_inserter(ranges), std::minus<float>());
-
- // maximal weight value across all channels
- float w_max = 0;
- {
- assert(max_values.size() == min_values.size());
- for (size_t i = 0; i < max_values.size(); ++i)
- {
- w_max = std::max(w_max, std::abs(max_values[i]));
- w_max = std::max(w_max, std::abs(min_values[i]));
- }
- }
-
- // total weight quantization error across all channels
- // so maximal error of quantization is ~ (max_value - min_value) / 255
- // omitting 255 term we get that maximal error of quantization is just its range
- float sum_err = 0.f;
- for (auto cur_err : ranges)
- {
- sum_err += cur_err;
- }
-
- uint32_t adds_per_channel = get_additions_per_channel(node);
- uint32_t num_of_channels = ranges.size();
-
- // maximal error introduced by weights quantization (for all channels)
- volume_W_A_err = sum_err * std::max(::fabs(ci_max), ::fabs(ci_min));
- // plus total error introduced by activation quantization (for all channels)
- volume_W_A_err += w_max * num_of_channels * ::fabs(ci_max - ci_min);
- // scale by volume of adds per channel
- volume_W_A_err *= adds_per_channel;
- // scale to get more readable output values
- volume_W_A_err /= 1.e+6f;
- }
-
- return volume_W_A_err;
-}
-
-} // namespace
-
-namespace mpqsolver
-{
-namespace bisection
-{
-
-/**
- * How Approximate works?
- *
- * Currently it works just for convolution layers, but may be generalized for other types as well.
- * See discussion at https://github.com/Samsung/ONE/pull/10170#discussion_r1042246598
- * Convolution can be expressed as a matrix multiplication.
- * While quantizing we introduce quantization error into convolution operand (activations) as well
- * as into convolution weights. A_q * W_q = (A + q_err(A)) * (W + q_err(W)) = A * W + A * q_err(W) +
- * W * q_err(A) + q_err(A) * q_err(W), assuming q_err(A) * q_err(W) are negligible as quadratic
- * terms, we get A_q * W_q ~ A * W + A * q_err(W) + W * q_err(A) , q_err - quantization error,
- * W - weight matrix, A - activations from previous layer (IFM), so quantization error of matrix
- * multiplication can be approximated as A * q_err(W) + W * q_err(A). Estimating its upper bound
- * we get A * q_err(W) + W * q_err(A) <=
- * number_of_additions * (A_max * (W_max - W_min) / 255 + W_max * (A_max - A_min) / 255)
- * The following code tries to get total error for quantizing convolution node into Q8.
- * It's just an heuristic (Metric sensitivity depends highly on derivatives as well).
- */
-float approximate(const CircleNode *node)
-{
- auto opcode = node->opcode();
- float qerror = 0.f;
- switch (opcode)
- {
- case CircleOpcode::DEPTHWISE_CONV_2D:
- case CircleOpcode::CONV_2D:
- case CircleOpcode::TRANSPOSE_CONV:
- qerror = approximate_conv(node);
- break;
- default: // TODO (FULLY_CONNECTED e.g.)
- qerror = 0.f;
- }
-
- return qerror;
-}
-
-} // namespace bisection
-} // namespace mpqsolver
diff --git a/compiler/circle-mpqsolver/src/bisection/ErrorApproximator.test.cpp b/compiler/circle-mpqsolver/src/bisection/ErrorApproximator.test.cpp
deleted file mode 100644
index 015f83bdc..000000000
--- a/compiler/circle-mpqsolver/src/bisection/ErrorApproximator.test.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <gtest/gtest.h>
-
-#include "ErrorApproximator.h"
-#include "TestHelper.h"
-
-#include <luci/IR/CircleNodeDecl.h>
-
-#include <cmath>
-
-namespace
-{
-
-inline uint32_t cal_offset(uint32_t shape[4], uint32_t *indices)
-{
- return indices[0] * shape[1] * shape[2] * shape[3] + indices[1] * shape[2] * shape[3] +
- indices[2] * shape[3] + indices[3];
-}
-
-class NConvGraph final : public SimpleGraph
-{
-protected:
- void initInput(loco::Node *input) override
- {
- auto ci_input = loco::must_cast<luci::CircleNode *>(input);
- ci_input->shape_status(luci::ShapeStatus::VALID);
- auto qparam = std::make_unique<luci::CircleQuantParam>();
- qparam->min.assign(_channel_size, _a_min);
- qparam->max.assign(_channel_size, _a_max);
- ci_input->quantparam(std::move(qparam));
- }
-
- loco::Node *insertGraphBody(loco::Node *input) override
- {
- _filter = _g->nodes()->create<luci::CircleConst>();
- _filter->dtype(loco::DataType::FLOAT32);
- _filter->shape({_channel_size, _f_w, _f_h, _channel_size});
- _filter->shape_status(luci::ShapeStatus::VALID);
- _filter->name("conv_filter");
- uint32_t indices[4] = {
- 0,
- };
-
- uint32_t w_shape[4] = {_filter->dim(0).value(), _filter->dim(1).value(),
- _filter->dim(2).value(), _filter->dim(3).value()};
-
- _filter->size<loco::DataType::FLOAT32>(w_shape[0] * w_shape[1] * w_shape[2] * w_shape[3]);
-
- for (indices[0] = 0; indices[0] < w_shape[0]; ++indices[0])
- {
- for (indices[1] = 0; indices[1] < w_shape[1]; ++indices[1])
- {
- for (indices[2] = 0; indices[2] < w_shape[2]; ++indices[2])
- {
- for (indices[3] = 0; indices[3] < w_shape[3]; ++indices[3])
- {
- uint32_t offset = cal_offset(w_shape, indices);
- _filter->at<loco::DataType::FLOAT32>(offset) = (offset % 2 == 0) ? _w_max : _w_min;
- }
- }
- }
- }
-
- _bias = _g->nodes()->create<luci::CircleConst>();
- _bias->dtype(loco::DataType::FLOAT32);
- _bias->shape({_channel_size});
- _bias->name("conv_bias");
-
- _conv = _g->nodes()->create<luci::CircleConv2D>();
- _conv->padding(luci::Padding::SAME);
- _conv->fusedActivationFunction(luci::FusedActFunc::NONE);
- _conv->dtype(loco::DataType::FLOAT32);
- _conv->shape({1, _width, _height, _channel_size});
- _conv->shape_status(luci::ShapeStatus::VALID);
- _conv->name("conv");
- _conv->filter(_filter);
- _conv->bias(_bias);
- _conv->input(input);
-
- return _conv;
- }
-
-public:
- luci::CircleConv2D *_conv = nullptr;
- luci::CircleConst *_filter = nullptr;
- luci::CircleConst *_bias = nullptr;
- uint32_t _f_w = 1;
- uint32_t _f_h = 1;
- float _w_min = -1.f;
- float _w_max = 1.f;
- float _a_min = -1.f;
- float _a_max = 1.f;
-};
-
-} // namespace
-
-TEST(CircleMPQSolverErrorApproximatorTest, verifyResultsTest)
-{
- NConvGraph g;
- g.init();
-
- auto value = mpqsolver::bisection::approximate(g._conv);
- float expected = ((g._w_max - g._w_min) * g._channel_size * std::max(g._a_max, g._a_min) +
- (g._a_max - g._a_min) * g._channel_size * std::max(g._w_max, g._w_min)) *
- g._f_h * g._f_w * g._height * g._width * g._channel_size / 1.e+6f;
- EXPECT_FLOAT_EQ(expected, value);
-}
-
-TEST(CircleMPQSolverErrorApproximatorTest, verifyResultsTest_NEG)
-{
- NConvGraph g;
- g.init();
-
- auto value = mpqsolver::bisection::approximate(g._input);
- float expected = 0.f;
- EXPECT_FLOAT_EQ(expected, value);
-
- value = mpqsolver::bisection::approximate(g._output);
- expected = 0.f;
- EXPECT_FLOAT_EQ(expected, value);
-}
diff --git a/compiler/circle-mpqsolver/src/bisection/VISQErrorApproximator.cpp b/compiler/circle-mpqsolver/src/bisection/VISQErrorApproximator.cpp
index 822df8925..ee6376a48 100644
--- a/compiler/circle-mpqsolver/src/bisection/VISQErrorApproximator.cpp
+++ b/compiler/circle-mpqsolver/src/bisection/VISQErrorApproximator.cpp
@@ -17,6 +17,7 @@
#include "VISQErrorApproximator.h"
#include <fstream>
+#include <json.h>
using namespace mpqsolver::bisection;
@@ -24,16 +25,30 @@ void VISQErrorApproximator::init(const std::string &visq_data_path)
{
// read file
std::ifstream file(visq_data_path);
- if (!init(file))
- {
- throw std::runtime_error("Invalid visq file " + visq_data_path);
- }
+ init(file);
}
-bool VISQErrorApproximator::init(std::istream &)
+void VISQErrorApproximator::init(std::istream &visq_data)
{
- // TODO
- return true;
+ Json::Reader reader;
+ Json::Value completeJsonData;
+ if (!reader.parse(visq_data, completeJsonData))
+ {
+ throw std::runtime_error("Invalid visq stream");
+ }
+
+ if (!completeJsonData.isMember("error"))
+ {
+ throw std::runtime_error("No 'error' section in visq stream");
+ }
+
+ auto layers = completeJsonData["error"][0];
+ auto names = layers.getMemberNames();
+ for (auto name : names)
+ {
+ auto value = layers[name].asFloat();
+ _layer_errors[name] = value;
+ }
}
float VISQErrorApproximator::approximate(const std::string &node_name) const
diff --git a/compiler/circle-mpqsolver/src/bisection/VISQErrorApproximator.h b/compiler/circle-mpqsolver/src/bisection/VISQErrorApproximator.h
index 855bca802..0d963cefb 100644
--- a/compiler/circle-mpqsolver/src/bisection/VISQErrorApproximator.h
+++ b/compiler/circle-mpqsolver/src/bisection/VISQErrorApproximator.h
@@ -45,9 +45,9 @@ public:
private:
/**
- * @brief initiliaze by visq_data (returns success)
+ * @brief initiliaze by visq_data (throws on failure)
*/
- bool init(std::istream &visq_data);
+ void init(std::istream &visq_data);
private:
std::string _visq_data_path;
diff --git a/compiler/circle-mpqsolver/src/bisection/VISQErrorApproximator.test.cpp b/compiler/circle-mpqsolver/src/bisection/VISQErrorApproximator.test.cpp
new file mode 100644
index 000000000..ccacb1ab7
--- /dev/null
+++ b/compiler/circle-mpqsolver/src/bisection/VISQErrorApproximator.test.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "VISQErrorApproximator.h"
+
+#include <json.h>
+#include <fstream>
+#include <gtest/gtest.h>
+
+namespace
+{
+
+void writeDataToFile(const std::string &path, const std::string &data)
+{
+ std::ofstream file;
+ file.open(path);
+ file << data;
+ file.close();
+}
+
+void makeTemporaryFile(char *name_template)
+{
+ int fd = mkstemp(name_template);
+ if (fd == -1)
+ {
+ throw std::runtime_error{"mkstemp failed"};
+ }
+}
+
+} // namespace
+
+TEST(CircleMPQSolverVISQErrorApproximatorTest, verifyResultsTest)
+{
+ static std::string errors_key = "error";
+ static std::string layer_key = "layer_0";
+ static float layer_error = 0.5f;
+ // trivial json with a single layer
+ Json::Value error_data;
+ Json::Value layer_data;
+ layer_data[layer_key] = layer_error;
+ error_data[errors_key].append(layer_data);
+
+ Json::StreamWriterBuilder builder;
+ auto data = Json::writeString(builder, error_data);
+
+ char path[] = "VISQErrorApproximator-TEST-XXXXXX";
+ makeTemporaryFile(path);
+ writeDataToFile(path, data);
+
+ mpqsolver::bisection::VISQErrorApproximator approximator;
+ EXPECT_NO_THROW(approximator.init(path));
+ EXPECT_FLOAT_EQ(approximator.approximate(layer_key), layer_error);
+ unlink(path);
+}
+
+TEST(CircleMPQSolverVISQErrorApproximatorTest, verifyResultsTest_NEG)
+{
+ Json::Value error_data;
+ // just an empty json
+ Json::StreamWriterBuilder builder;
+ auto data = Json::writeString(builder, error_data);
+
+ char path[] = "VISQErrorApproximator-TEST-NEG-XXXXXX";
+ makeTemporaryFile(path);
+ writeDataToFile(path, data);
+
+ mpqsolver::bisection::VISQErrorApproximator approximator;
+ EXPECT_THROW(approximator.init(path), std::exception);
+ unlink(path);
+}
diff --git a/compiler/circle-mpqsolver/src/core/Dumper.cpp b/compiler/circle-mpqsolver/src/core/Dumper.cpp
new file mode 100644
index 000000000..3a94cb3fa
--- /dev/null
+++ b/compiler/circle-mpqsolver/src/core/Dumper.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Dumper.h"
+
+#include <luci/CircleExporter.h>
+#include <luci/CircleFileExpContract.h>
+
+#include <json.h>
+#include <fstream>
+#include <sys/stat.h>
+
+using namespace mpqsolver::core;
+
+namespace
+{
+
+const std::string default_dtype_key = "default_quantization_dtype";
+const std::string default_granularity_key = "default_granularity";
+const std::string layers_key = "layers";
+const std::string model_key = "model_path";
+const std::string layer_name_key = "name";
+const std::string layer_dtype_key = "dtype";
+const std::string layer_granularity_key = "granularity";
+
+} // namespace
+
+Dumper::Dumper(const std::string &dir_path) : _dir_path(dir_path) {}
+
+void Dumper::set_model_path(const std::string &model_path) { _model_path = model_path; }
+
+void Dumper::dump_MPQ_configuration(const LayerParams &layers, const std::string &def_dtype,
+ const std::string &path) const
+{
+ Json::Value mpq_data;
+ mpq_data[default_dtype_key] = def_dtype;
+ mpq_data[default_granularity_key] = "channel";
+ mpq_data[model_key] = _model_path;
+
+ Json::Value layers_data;
+ for (auto &layer : layers)
+ {
+ Json::Value layer_data;
+ layer_data[layer_name_key] = layer->name;
+ layer_data[layer_granularity_key] = layer->granularity;
+ layer_data[layer_dtype_key] = layer->dtype;
+ layers_data.append(layer_data);
+ }
+ mpq_data[layers_key] = layers_data;
+
+ Json::StreamWriterBuilder builder;
+ auto data = Json::writeString(builder, mpq_data);
+
+ write_data_to_file(path, data);
+}
+
+void Dumper::prepare_directory(const std::string &dir_path) const
+{
+ struct stat sb;
+ if (stat(dir_path.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode))
+ {
+ if (mkdir(dir_path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)
+ {
+ throw std::runtime_error("Failed to create directory for dumping intermediate results");
+ }
+ }
+}
+
+void Dumper::dump_MPQ_configuration(const LayerParams &layers, const std::string &def_dtype,
+ int step) const
+{
+ prepare_directory(_dir_path);
+ std::string path = _dir_path + "/Configuration_" + std::to_string(step) + ".mpq.json";
+ dump_MPQ_configuration(layers, def_dtype, path);
+}
+
+void Dumper::dump_final_MPQ(const LayerParams &layers, const std::string &def_dtype) const
+{
+ prepare_directory(_dir_path);
+ std::string path = _dir_path + "/FinalConfiguration" + ".mpq.json";
+ dump_MPQ_configuration(layers, def_dtype, path);
+}
+
+void Dumper::write_data_to_file(const std::string &path, const std::string &data) const
+{
+ std::ofstream file;
+ file.open(path);
+ file << data;
+ file.close();
+}
+
+void Dumper::save_circle(luci::Module *module, std::string &path) const
+{
+ luci::CircleExporter exporter;
+ luci::CircleFileExpContract contract(module, path);
+ if (!exporter.invoke(&contract))
+ {
+ throw std::runtime_error("Failed to export circle model to " + path);
+ }
+}
+
+void Dumper::dump_quantized(luci::Module *module, uint32_t step) const
+{
+ std::string path = _dir_path + "/quantized_" + std::to_string(step) + ".mpq.circle";
+ save_circle(module, path);
+}
+
+void Dumper::dump_error(float error, const std::string &tag, const std::string &path) const
+{
+ std::ofstream file;
+ file.open(path, std::ios_base::app);
+ file << tag << " " << error << std::endl;
+ file.close();
+}
+
+void Dumper::prepare_for_error_dumping() const
+{
+ prepare_directory(_dir_path);
+ std::string path = get_error_path();
+ std::ofstream file;
+ file.open(path); // create empty
+ file.close();
+}
+
+void Dumper::dump_Q8_error(float error) const
+{
+ std::string path = get_error_path();
+ dump_error(error, "Q8", path);
+}
+
+void Dumper::dump_Q16_error(float error) const
+{
+ std::string path = get_error_path();
+ dump_error(error, "Q16", path);
+}
+
+void Dumper::dump_MPQ_error(float error, uint32_t step) const
+{
+ std::string path = get_error_path();
+ dump_error(error, std::to_string(step), path);
+}
+
+void Dumper::dump_MPQ_error(float error) const
+{
+ std::string path = get_error_path();
+ dump_error(error, "FINAL", path);
+}
diff --git a/compiler/circle-mpqsolver/src/core/Dumper.h b/compiler/circle-mpqsolver/src/core/Dumper.h
new file mode 100644
index 000000000..220b54a20
--- /dev/null
+++ b/compiler/circle-mpqsolver/src/core/Dumper.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MPQSOLVER_DUMPER_H__
+#define __MPQSOLVER_DUMPER_H__
+
+#include <luci/IR/Module.h>
+#include <luci/CircleQuantizer.h>
+
+#include <string>
+
+namespace mpqsolver
+{
+namespace core
+{
+
+using LayerParam = luci::CircleQuantizer::Options::LayerParam;
+using LayerParams = std::vector<std::shared_ptr<LayerParam>>;
+
+class Dumper final
+{
+public:
+ Dumper() = default;
+ Dumper(const std::string &dir_path);
+
+ /**
+ * @brief sets model path for further usage
+ */
+ void set_model_path(const std::string &model_path);
+
+ /**
+ * @brief dumps mpq configuration
+ * @param layers specific quantization parameters
+ * @param def_dtype default quantization data type
+ * @param step id of mpq configuration
+ */
+ void dump_MPQ_configuration(const LayerParams &layers, const std::string &def_dtype,
+ int step) const;
+
+ /**
+ * @brief dumps final mpq configuration
+ * @param layers specific quantization parameters
+ * @param def_dtype default quantization data type
+ */
+ void dump_final_MPQ(const LayerParams &layers, const std::string &def_dtype) const;
+
+ /**
+ * @brief dumps quantized module
+ * @param layers specific quantization parameters
+ * @param step id of quantized module
+ */
+ void dump_quantized(luci::Module *module, uint32_t step) const;
+
+ /**
+ * @brief create file for error dumping
+ */
+ void prepare_for_error_dumping() const;
+
+ /**
+ * @brief append error of Q8 quantization
+ */
+ void dump_Q8_error(float error) const;
+
+ /**
+ * @brief append error of Q16 quantization
+ */
+ void dump_Q16_error(float error) const;
+
+ /**
+ * @brief append error of mpq quantization
+ * @param error error of quantization
+ * @param step id of error
+ */
+ void dump_MPQ_error(float error, uint32_t step) const;
+
+ /**
+ * @brief dump final error
+ * @param error final error of quantization
+ */
+ void dump_MPQ_error(float error) const;
+
+private:
+ void write_data_to_file(const std::string &path, const std::string &data) const;
+ void dump_MPQ_configuration(const LayerParams &layers, const std::string &def_dtype,
+ const std::string &path) const;
+ void prepare_directory(const std::string &dir_path) const;
+ void save_circle(luci::Module *module, std::string &path) const;
+ void dump_error(float error, const std::string &tag, const std::string &path) const;
+ std::string get_error_path() const { return _dir_path + "/errors" + ".mpq.txt"; }
+
+private:
+ std::string _dir_path;
+ std::string _model_path;
+
+}; // Dumper
+
+} // namespace core
+} // namespace mpqsolver
+
+#endif //__MPQSOLVER_DUMPER_H__
diff --git a/compiler/circle-mpqsolver/src/core/DumpingHooks.cpp b/compiler/circle-mpqsolver/src/core/DumpingHooks.cpp
new file mode 100644
index 000000000..4d0522bdd
--- /dev/null
+++ b/compiler/circle-mpqsolver/src/core/DumpingHooks.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "DumpingHooks.h"
+
+using namespace mpqsolver::core;
+
+DumpingHooks::DumpingHooks(const std::string &save_path)
+ : _save_path(save_path), _dumper(_save_path)
+{
+}
+
+void DumpingHooks::on_begin_solver(const std::string &model_path, float q8error, float q16error)
+{
+ _model_path = model_path;
+ _dumper.set_model_path(_model_path);
+ _dumper.prepare_for_error_dumping();
+ _dumper.dump_Q8_error(q8error);
+ _dumper.dump_Q16_error(q16error);
+}
+
+void DumpingHooks::on_begin_iteration()
+{
+ _in_iterations = true;
+ _num_of_iterations += 1;
+}
+
+void DumpingHooks::on_end_iteration(const LayerParams &layers, const std::string &def_type,
+ float error) const
+{
+ _dumper.dump_MPQ_configuration(layers, def_type, _num_of_iterations);
+ _dumper.dump_MPQ_error(error, _num_of_iterations);
+}
+
+void DumpingHooks::on_end_solver(const LayerParams &layers, const std::string &def_dtype,
+ float qerror)
+{
+ _dumper.dump_final_MPQ(layers, def_dtype);
+ _dumper.dump_MPQ_error(qerror);
+ _in_iterations = false;
+}
+
+void DumpingHooks::on_quantized(luci::Module *module) const
+{
+ if (_in_iterations)
+ {
+ _dumper.dump_quantized(module, _num_of_iterations);
+ }
+}
diff --git a/compiler/circle-mpqsolver/src/core/DumpingHooks.h b/compiler/circle-mpqsolver/src/core/DumpingHooks.h
new file mode 100644
index 000000000..c432a9a40
--- /dev/null
+++ b/compiler/circle-mpqsolver/src/core/DumpingHooks.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MPQSOLVER_DUMPING_HOOKS_H__
+#define __MPQSOLVER_DUMPING_HOOKS_H__
+
+#include <luci/IR/Module.h>
+
+#include <core/Quantizer.h>
+#include <core/SolverHooks.h>
+#include <core/Dumper.h>
+
+#include <string>
+
+namespace mpqsolver
+{
+namespace core
+{
+
+/**
+ * @brief DumpingHooks is intended to save intermediate results
+ */
+class DumpingHooks final : public QuantizerHook, public SolverHooks
+{
+public:
+ /**
+ * @brief DumpingHooks constructor
+ * @param save_path directory where all intermediate data will be saved
+ */
+ DumpingHooks(const std::string &save_path);
+
+ /**
+ * @brief called on successfull quantization
+ */
+ virtual void on_quantized(luci::Module *module) const override;
+
+ /**
+ * @brief called on the start of iterative search
+ */
+ virtual void on_begin_solver(const std::string &model_path, float q8error,
+ float q16error) override;
+
+ /**
+ * @brief called on the start of current iteration
+ */
+ virtual void on_begin_iteration() override;
+
+ /**
+ * @brief called at the end of current iteration
+ */
+ virtual void on_end_iteration(const LayerParams &layers, const std::string &def_dtype,
+ float error) const override;
+
+ /**
+ * @brief called at the end of iterative search
+ */
+ virtual void on_end_solver(const LayerParams &layers, const std::string &def_dtype,
+ float qerror) override;
+
+protected:
+ std::string _model_path;
+ std::string _save_path;
+ Dumper _dumper;
+ uint32_t _num_of_iterations = 0;
+ bool _in_iterations = false;
+};
+
+} // namespace core
+} // namespace mpqsolver
+
+#endif //__MPQSOLVER_DUMPING_HOOKS_H__
diff --git a/compiler/circle-mpqsolver/src/bisection/ErrorMetric.cpp b/compiler/circle-mpqsolver/src/core/ErrorMetric.cpp
index 74c7fd68a..23ddfcb7d 100644
--- a/compiler/circle-mpqsolver/src/bisection/ErrorMetric.cpp
+++ b/compiler/circle-mpqsolver/src/core/ErrorMetric.cpp
@@ -22,7 +22,7 @@
#include <cmath>
#include <cassert>
-using namespace mpqsolver::bisection;
+using namespace mpqsolver::core;
/**
* @brief compare first and second operands in MAE (Mean Average Error metric)
@@ -56,5 +56,10 @@ float MAEMetric::compute(const WholeOutput &first, const WholeOutput &second) co
}
}
+ if (output_size == 0)
+ {
+ throw std::runtime_error("nothing to compare");
+ }
+
return error / output_size;
}
diff --git a/compiler/circle-mpqsolver/src/bisection/ErrorMetric.h b/compiler/circle-mpqsolver/src/core/ErrorMetric.h
index 9ef86628b..fc535396e 100644
--- a/compiler/circle-mpqsolver/src/bisection/ErrorMetric.h
+++ b/compiler/circle-mpqsolver/src/core/ErrorMetric.h
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-#ifndef __MPQSOLVER_BISECTION_ERROR_METRIC_H__
-#define __MPQSOLVER_BISECTION_ERROR_METRIC_H__
+#ifndef __MPQSOLVER_CORE_ERROR_METRIC_H__
+#define __MPQSOLVER_CORE_ERROR_METRIC_H__
#include <vector>
namespace mpqsolver
{
-namespace bisection
+namespace core
{
using Buffer = std::vector<char>;
@@ -49,7 +49,7 @@ public:
float compute(const WholeOutput &first, const WholeOutput &second) const;
};
-} // namespace bisection
+} // namespace core
} // namespace mpqsolver
-#endif //__MPQSOLVER_BISECTION_ERROR_METRIC_H__
+#endif //__MPQSOLVER_CORE_ERROR_METRIC_H__
diff --git a/compiler/circle-mpqsolver/src/core/ErrorMetric.test.cpp b/compiler/circle-mpqsolver/src/core/ErrorMetric.test.cpp
new file mode 100644
index 000000000..232d9bc60
--- /dev/null
+++ b/compiler/circle-mpqsolver/src/core/ErrorMetric.test.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ErrorMetric.h"
+
+#include <gtest/gtest.h>
+
+TEST(CircleMPQSolverMAEMetricTest, verifyResultsTest)
+{
+ size_t num_elements = 512;
+ mpqsolver::core::WholeOutput target, source;
+ // let target be zero
+ {
+ std::vector<float> float_buffer(num_elements, 0.f);
+ auto const char_buffer = reinterpret_cast<char *>(float_buffer.data());
+ auto const char_buffer_size = num_elements * sizeof(float) / sizeof(char);
+ std::vector<char> buffer(char_buffer, char_buffer + char_buffer_size);
+
+ mpqsolver::core::Output out = mpqsolver::core::Output(1, buffer);
+ target = mpqsolver::core::WholeOutput(1, out);
+ }
+
+ // let source be one
+ {
+ std::vector<float> float_buffer(num_elements, 1.f);
+ auto const char_buffer = reinterpret_cast<char *>(float_buffer.data());
+ auto const char_buffer_size = num_elements * sizeof(float) / sizeof(char);
+ std::vector<char> buffer(char_buffer, char_buffer + char_buffer_size);
+ mpqsolver::core::Output out = mpqsolver::core::Output(1, buffer);
+ source = mpqsolver::core::WholeOutput(1, out);
+ }
+
+ mpqsolver::core::MAEMetric metric;
+ float value = metric.compute(target, source);
+ EXPECT_FLOAT_EQ(value, 1.f);
+}
+
+TEST(CircleMPQSolverMAEMetricTest, verifyResultsTest_NEG)
+{
+ mpqsolver::core::MAEMetric metric;
+ mpqsolver::core::WholeOutput target, source;
+ EXPECT_ANY_THROW(metric.compute(target, source));
+}
diff --git a/compiler/circle-mpqsolver/src/bisection/Evaluator.cpp b/compiler/circle-mpqsolver/src/core/Evaluator.cpp
index 94d46a39c..c7afda5c2 100644
--- a/compiler/circle-mpqsolver/src/bisection/Evaluator.cpp
+++ b/compiler/circle-mpqsolver/src/core/Evaluator.cpp
@@ -20,7 +20,7 @@
#include <dio_hdf5/HDF5Importer.h>
-using namespace mpqsolver::bisection;
+using namespace mpqsolver::core;
using Shape = std::vector<loco::Dimension>;
@@ -69,12 +69,13 @@ WholeOutput compute_outputs(const luci::Module *module, const std::string &h5fil
{
loco::DataType dtype;
Shape shape;
- importer.readTensor(record_idx, input_idx, &dtype, &shape, input_data.data());
+ importer.readTensor(record_idx, input_idx, &dtype, &shape, input_data.data(),
+ input_data.size());
}
else
{
// Skip type/shape check for raw data
- importer.readTensor(record_idx, input_idx, input_data.data());
+ importer.readTensor(record_idx, input_idx, input_data.data(), input_data.size());
}
interpreter.writeInputTensor(input_node, input_data.data(), input_data.size());
diff --git a/compiler/circle-mpqsolver/src/bisection/Evaluator.h b/compiler/circle-mpqsolver/src/core/Evaluator.h
index 144c86c68..9820508bc 100644
--- a/compiler/circle-mpqsolver/src/bisection/Evaluator.h
+++ b/compiler/circle-mpqsolver/src/core/Evaluator.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef __MPQSOLVER_BISECTION_EVALUATOR_H__
-#define __MPQSOLVER_BISECTION_EVALUATOR_H__
+#ifndef __MPQSOLVER_CORE_EVALUATOR_H__
+#define __MPQSOLVER_CORE_EVALUATOR_H__
#include "ErrorMetric.h"
@@ -27,7 +27,7 @@
namespace mpqsolver
{
-namespace bisection
+namespace core
{
class DatasetEvaluator final
@@ -60,7 +60,7 @@ private:
const ErrorMetric *_metric = nullptr;
};
-} // namespace bisection
+} // namespace core
} // namespace mpqsolver
-#endif //__MPQSOLVER_BISECTION_EVALUATOR_H__
+#endif //__MPQSOLVER_CORE_EVALUATOR_H__
diff --git a/compiler/circle-mpqsolver/src/bisection/Quantizer.cpp b/compiler/circle-mpqsolver/src/core/Quantizer.cpp
index 6fe1d560b..421793197 100644
--- a/compiler/circle-mpqsolver/src/bisection/Quantizer.cpp
+++ b/compiler/circle-mpqsolver/src/core/Quantizer.cpp
@@ -19,7 +19,7 @@
#include <iostream>
-using namespace mpqsolver::bisection;
+using namespace mpqsolver::core;
using AlgorithmParameters = luci::CircleQuantizer::Options::AlgorithmParameters;
using Algorithms = luci::CircleQuantizer::Options::Algorithm;
@@ -54,6 +54,8 @@ Quantizer::Quantizer(const std::string &input_dtype, const std::string &output_d
{
}
+void Quantizer::set_hook(const QuantizerHook *hook) { _hook = hook; }
+
/**
* @brief quantize recorded module (min/max initialized) with specified parameters
* returns true on success
@@ -104,6 +106,11 @@ bool Quantizer::quantize(luci::Module *module, const std::string &quant_dtype,
}
}
+ if (_hook)
+ {
+ _hook->on_quantized(module);
+ }
+
return true;
}
diff --git a/compiler/circle-mpqsolver/src/bisection/Quantizer.h b/compiler/circle-mpqsolver/src/core/Quantizer.h
index ceaabf572..259d5c4b0 100644
--- a/compiler/circle-mpqsolver/src/bisection/Quantizer.h
+++ b/compiler/circle-mpqsolver/src/core/Quantizer.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef __MPQSOLVER_BISECTION_QUANTIZER_H__
-#define __MPQSOLVER_BISECTION_QUANTIZER_H__
+#ifndef __MPQSOLVER_CORE_QUANTIZER_H__
+#define __MPQSOLVER_CORE_QUANTIZER_H__
#include <luci/IR/Module.h>
#include <luci/CircleQuantizer.h>
@@ -26,18 +26,32 @@
namespace mpqsolver
{
-namespace bisection
+namespace core
{
using LayerParam = luci::CircleQuantizer::Options::LayerParam;
using LayerParams = std::vector<std::shared_ptr<LayerParam>>;
+struct QuantizerHook
+{
+ /**
+ * @brief called on successfull quantization
+ * @param module quantized module
+ */
+ virtual void on_quantized(luci::Module *module) const = 0;
+};
+
class Quantizer
{
public:
Quantizer(const std::string &input_dtype, const std::string &output_type);
/**
+ * @brief set hook on the end of quantization event
+ */
+ void set_hook(const QuantizerHook *callback);
+
+ /**
* @brief quantize recorded module (min/max initialized) with specified parameters
* returns true on success
*/
@@ -53,9 +67,10 @@ public:
private:
std::string _input_dtype = "uint8";
std::string _output_dtype = "uint8";
+ const QuantizerHook *_hook = nullptr;
};
-} // namespace bisection
+} // namespace core
} // namespace mpqsolver
-#endif //__MPQSOLVER_BISECTION_QUANTIZER_H__
+#endif //__MPQSOLVER_CORE_QUANTIZER_H__
diff --git a/compiler/circle-mpqsolver/src/bisection/Quantizer.test.cpp b/compiler/circle-mpqsolver/src/core/Quantizer.test.cpp
index 8575156d2..7d7e74fdc 100644
--- a/compiler/circle-mpqsolver/src/bisection/Quantizer.test.cpp
+++ b/compiler/circle-mpqsolver/src/core/Quantizer.test.cpp
@@ -85,8 +85,8 @@ TEST(CircleMPQSolverQuantizerTest, verifyResultsTest)
g.transfer_to(m.get());
std::string def_quant = "uint8";
- mpqsolver::bisection::Quantizer quantizer(def_quant, def_quant);
- mpqsolver::bisection::LayerParams params;
+ mpqsolver::core::Quantizer quantizer(def_quant, def_quant);
+ mpqsolver::core::LayerParams params;
auto res = quantizer.quantize(m.get(), def_quant, params);
EXPECT_TRUE(res);
auto quant_param = add->quantparam();
@@ -100,8 +100,8 @@ TEST(CircleMPQSolverQuantizerTest, verifyResultsTest)
TEST(CircleMPQSolverQuantizerTest, verifyResultsTest_NEG)
{
std::string def_quant = "uint8";
- mpqsolver::bisection::Quantizer quantizer(def_quant, def_quant);
- mpqsolver::bisection::LayerParams params;
+ mpqsolver::core::Quantizer quantizer(def_quant, def_quant);
+ mpqsolver::core::LayerParams params;
auto res = quantizer.quantize(nullptr, def_quant, params);
EXPECT_TRUE(!res);
}
diff --git a/onert-micro/luci-interpreter/pal/linux/PALFill.h b/compiler/circle-mpqsolver/src/core/SolverHooks.cpp
index 212350a8b..bbe1bb4a3 100644
--- a/onert-micro/luci-interpreter/pal/linux/PALFill.h
+++ b/compiler/circle-mpqsolver/src/core/SolverHooks.cpp
@@ -1,6 +1,5 @@
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,9 +14,4 @@
* limitations under the License.
*/
-#ifndef LUCI_INTERPRETER_PAL_FILL_H
-#define LUCI_INTERPRETER_PAL_FILL_H
-
-#include "tensorflow/lite/kernels/internal/reference/reference_ops.h"
-
-#endif // LUCI_INTERPRETER_PAL_FILL_H
+#include "SolverHooks.h"
diff --git a/compiler/circle-mpqsolver/src/core/SolverHooks.h b/compiler/circle-mpqsolver/src/core/SolverHooks.h
new file mode 100644
index 000000000..851a69993
--- /dev/null
+++ b/compiler/circle-mpqsolver/src/core/SolverHooks.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MPQSOLVER_SOLVER_HOOKS_H__
+#define __MPQSOLVER_SOLVER_HOOKS_H__
+
+#include <luci/IR/Module.h>
+
+#include <core/Quantizer.h>
+
+#include <string>
+
+namespace mpqsolver
+{
+namespace core
+{
+
+class SolverHooks
+{
+public:
+ /**
+ * @brief called on the start of iterative search
+ * @param model_path path of original float model to quantize
+ * @param q8error error of Q8 quantization
+ * @param q16error error of Q16 quantization
+ */
+ virtual void on_begin_solver(const std::string &model_path, float q8error, float q16error) = 0;
+
+ /**
+ * @brief called on the start of current iteration
+ */
+ virtual void on_begin_iteration() = 0;
+
+ /**
+ * @brief called at the end of current iteration
+ * @param layers model nodes with specific quantization parameters
+ * @param def_dtype default quantization dtype
+ * @param error error of quantization for current iteration
+ */
+ virtual void on_end_iteration(const LayerParams &layers, const std::string &def_dtype,
+ float error) const = 0;
+
+ /**
+ * @brief called at the end of iterative search
+ * @param layers model nodes with specific quantization parameters
+ * @param def_dtype default quantization dtype
+ * @param qerror final error of quantization
+ */
+ virtual void on_end_solver(const LayerParams &layers, const std::string &def_dtype,
+ float qerror) = 0;
+};
+
+} // namespace core
+} // namespace mpqsolver
+
+#endif //__MPQSOLVER_SOLVER_HOOKS_H__
diff --git a/compiler/circle-mpqsolver/src/core/SolverOutput.cpp b/compiler/circle-mpqsolver/src/core/SolverOutput.cpp
new file mode 100644
index 000000000..c14fe30f7
--- /dev/null
+++ b/compiler/circle-mpqsolver/src/core/SolverOutput.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SolverOutput.h"
+
+#include <iostream>
+
+SolverOutput &SolverOutput::get(void)
+{
+ static SolverOutput d;
+ return d;
+}
+
+const SolverOutput &SolverOutput::operator<<(const std::string &message) const
+{
+ if (_turn_on)
+ {
+ std::cout << message;
+ }
+
+ return *this;
+}
+
+const SolverOutput &SolverOutput::operator<<(float value) const
+{
+ if (_turn_on)
+ {
+ std::cout << value;
+ }
+
+ return *this;
+}
+
+void SolverOutput::TurnOn(bool on) { _turn_on = on; }
diff --git a/compiler/circle-mpqsolver/src/core/SolverOutput.h b/compiler/circle-mpqsolver/src/core/SolverOutput.h
new file mode 100644
index 000000000..218d3b95e
--- /dev/null
+++ b/compiler/circle-mpqsolver/src/core/SolverOutput.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MPQSOLVER_SOLVER_OUTPUT_H__
+#define __MPQSOLVER_SOLVER_OUTPUT_H__
+
+#include <string>
+
+/**
+ * @brief SolverOutput prints important performance information
+ */
+class SolverOutput
+{
+private:
+ /**
+ * @brief construct SolverOutput
+ */
+ SolverOutput() = default;
+
+public:
+ /**
+ * @brief get singleton object
+ */
+ static SolverOutput &get(void);
+
+ /**
+ * @brief print string message
+ */
+ const SolverOutput &operator<<(const std::string &message) const;
+
+ /**
+ * @brief print float value
+ */
+ const SolverOutput &operator<<(float value) const;
+
+ /**
+ * @brief turn on/off actual output
+ */
+ void TurnOn(bool on);
+
+private:
+ bool _turn_on = true;
+};
+
+#endif // __MPQSOLVER_SOLVER_OUTPUT_H__
diff --git a/compiler/circle-mpqsolver/src/bisection/TestHelper.h b/compiler/circle-mpqsolver/src/core/TestHelper.h
index f930738f9..f930738f9 100644
--- a/compiler/circle-mpqsolver/src/bisection/TestHelper.h
+++ b/compiler/circle-mpqsolver/src/core/TestHelper.h
diff --git a/compiler/circle-operator/CMakeLists.txt b/compiler/circle-operator/CMakeLists.txt
index 6817a8618..33d9a96d0 100644
--- a/compiler/circle-operator/CMakeLists.txt
+++ b/compiler/circle-operator/CMakeLists.txt
@@ -1,6 +1,6 @@
-if(NOT TARGET mio_circle04)
+if(NOT TARGET mio_circle06)
return()
-endif(NOT TARGET mio_circle04)
+endif(NOT TARGET mio_circle06)
set(DRIVER "driver/Driver.cpp")
@@ -10,8 +10,8 @@ add_executable(circle-operator ${DRIVER} ${SOURCES})
target_include_directories(circle-operator PRIVATE src)
target_link_libraries(circle-operator arser)
target_link_libraries(circle-operator foder)
-target_link_libraries(circle-operator mio_circle04)
-target_link_libraries(circle-operator mio_circle04_helper)
+target_link_libraries(circle-operator mio_circle06)
+target_link_libraries(circle-operator mio_circle06_helper)
target_link_libraries(circle-operator safemain)
install(TARGETS circle-operator DESTINATION bin)
diff --git a/compiler/circle-operator/requires.cmake b/compiler/circle-operator/requires.cmake
index 183dfe227..b3a2638ef 100644
--- a/compiler/circle-operator/requires.cmake
+++ b/compiler/circle-operator/requires.cmake
@@ -1,4 +1,4 @@
require("arser")
require("foder")
-require("mio-circle04")
+require("mio-circle06")
require("safemain")
diff --git a/compiler/circle-opselector/driver/Driver.cpp b/compiler/circle-opselector/driver/Driver.cpp
index 6549fc7f6..5ad2b9ca3 100644
--- a/compiler/circle-opselector/driver/Driver.cpp
+++ b/compiler/circle-opselector/driver/Driver.cpp
@@ -102,7 +102,11 @@ int entry(int argc, char **argv)
new_module = op_selector.select_by<opselector::SelectType::NAME>(operator_input);
}
- assert(opselector::exportModule(new_module.get(), output_path));
+ if (not opselector::exportModule(new_module.get(), output_path))
+ {
+ std::cerr << "ERROR: Cannot export the module" << std::endl;
+ return EXIT_FAILURE;
+ }
return 0;
}
diff --git a/compiler/circle-opselector/src/OpSelector.cpp b/compiler/circle-opselector/src/OpSelector.cpp
index 31cbf9c0c..09a66548d 100644
--- a/compiler/circle-opselector/src/OpSelector.cpp
+++ b/compiler/circle-opselector/src/OpSelector.cpp
@@ -156,6 +156,10 @@ std::unique_ptr<loco::Graph> make_graph(const std::vector<const luci::CircleNode
}
}
}
+
+ const auto original_graph = nodes.at(0)->graph();
+ const auto original_outputs = loco::output_nodes(const_cast<loco::Graph *>(original_graph));
+
// set graph output
for (auto &n : nodes)
{
@@ -169,8 +173,19 @@ std::unique_ptr<loco::Graph> make_graph(const std::vector<const luci::CircleNode
break;
}
}
+
+ bool originalOutput = false;
+ for (const auto &o : outputs)
+ {
+ if (std::find(original_outputs.begin(), original_outputs.end(), o) != original_outputs.end())
+ {
+ originalOutput = true;
+ break;
+ }
+ }
+
// the node isn't graph output if it is an other node's output
- if (beingUsed)
+ if (beingUsed and not originalOutput)
continue;
IsMultiOutputNode multiout_visitor;
@@ -335,7 +350,7 @@ OpSelector::select_by<SelectType::NAME>(const std::vector<std::string> &tokens)
auto cnode = loco::must_cast<const luci::CircleNode *>(node);
std::string node_name = cnode->name();
- for (auto selected_name : tokens)
+ for (const auto &selected_name : tokens)
if (selected_name.compare(node_name) == 0) // find the selected name
selected_nodes.emplace_back(cnode);
}
diff --git a/compiler/circle-part-value-test/CMakeLists.txt b/compiler/circle-part-value-test/CMakeLists.txt
index c4bd20047..04ad830d3 100644
--- a/compiler/circle-part-value-test/CMakeLists.txt
+++ b/compiler/circle-part-value-test/CMakeLists.txt
@@ -107,17 +107,7 @@ add_dependencies(circle_part_value_test_prepare common_artifacts_deps)
add_test(NAME circle_part_value_test
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/part_eval_all.sh"
"${CMAKE_CURRENT_BINARY_DIR}"
- "${NNCC_OVERLAY_DIR}/venv_2_8_0"
+ "${NNCC_OVERLAY_DIR}/venv_2_12_1"
"$<TARGET_FILE:circle_part_driver>"
${PARTITION_LIST}
)
-
-if(ONE_UBUNTU_CODENAME_JAMMY)
- add_test(NAME circle_part_value_210_test
- COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/part_eval_all.sh"
- "${CMAKE_CURRENT_BINARY_DIR}"
- "${NNCC_OVERLAY_DIR}/venv_2_10_1"
- "$<TARGET_FILE:circle_part_driver>"
- ${PARTITION_LIST}
- )
-endif(ONE_UBUNTU_CODENAME_JAMMY)
diff --git a/compiler/circle-quantizer-dredd-recipe-test/CMakeLists.txt b/compiler/circle-quantizer-dredd-recipe-test/CMakeLists.txt
index a9420d463..adb2c0f2f 100644
--- a/compiler/circle-quantizer-dredd-recipe-test/CMakeLists.txt
+++ b/compiler/circle-quantizer-dredd-recipe-test/CMakeLists.txt
@@ -82,6 +82,25 @@ macro(AddFakeQuant RECIPE)
list(APPEND TEST_NAMES ${RECIPE})
endmacro(AddFakeQuant)
+# Macro to generate re-quantized models
+macro(AddReQuant RECIPE)
+ set(CIRCLE_PATH "${ARTIFACTS_BIN_PATH}/${RECIPE}.circle")
+ # NOTE We use .q.circle because it is convention for output file (see testall.sh for more details)
+ set(REQUANT_CIRCLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${RECIPE}.q.circle")
+
+ # Generate re-quantized .circle
+ add_custom_command(OUTPUT ${REQUANT_CIRCLE_PATH}
+ COMMAND $<TARGET_FILE:circle-quantizer> --requantize int8 uint8 ${CIRCLE_PATH} ${REQUANT_CIRCLE_PATH}
+ DEPENDS
+ circle-quantizer
+ ${CIRCLE_PATH}
+ COMMENT "Generate ${RECIPE}.q.circle"
+ )
+
+ list(APPEND TEST_DEPS ${REQUANT_CIRCLE_PATH})
+ list(APPEND TEST_NAMES ${RECIPE})
+endmacro(AddReQuant)
+
# Macro to quantize without quantize_dequantize_weights
macro(AddSkipQDQW RECIPE)
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
diff --git a/compiler/circle-quantizer-dredd-recipe-test/test.lst b/compiler/circle-quantizer-dredd-recipe-test/test.lst
index 146408383..309069bb8 100644
--- a/compiler/circle-quantizer-dredd-recipe-test/test.lst
+++ b/compiler/circle-quantizer-dredd-recipe-test/test.lst
@@ -73,6 +73,18 @@ AddFakeQuant(Quant_Add_000)
AddFakeQuant(Quant_DepthToSpace_000)
AddFakeQuant(Quant_SpaceToDepth_000)
+# Requantize Test (I8 -> U8)
+AddReQuant(Quant_Add_I8_000)
+AddReQuant(Quant_AveragePool2D_I8_000)
+AddReQuant(Quant_Conv_I8_000)
+AddReQuant(Quant_DepthwiseConv2D_I8_000)
+AddReQuant(Quant_MaxPool2D_I8_000)
+AddReQuant(Quant_Mean_I8_000)
+AddReQuant(Quant_Mul_I8_000)
+AddReQuant(Quant_PRelu_I8_000)
+AddReQuant(Quant_ReLU_I8_000)
+AddReQuant(Quant_TransposeConv_I8_000)
+
## CIRCLE RECIPE
# MPQ Test (default: u8, target: s16)
diff --git a/compiler/circle-quantizer/src/CircleQuantizer.cpp b/compiler/circle-quantizer/src/CircleQuantizer.cpp
index 33a845c96..02b96f91e 100644
--- a/compiler/circle-quantizer/src/CircleQuantizer.cpp
+++ b/compiler/circle-quantizer/src/CircleQuantizer.cpp
@@ -94,6 +94,7 @@ void print_exclusive_options(void)
std::cout << " --quantize_with_minmax" << std::endl;
std::cout << " --requantize" << std::endl;
std::cout << " --force_quantparam" << std::endl;
+ std::cout << " --quantize_weights" << std::endl;
}
void print_version(void)
@@ -115,6 +116,7 @@ int entry(int argc, char **argv)
const std::string fq = "--force_quantparam";
const std::string cq = "--copy_quantparam";
const std::string fake_quant = "--fake_quantize";
+ const std::string qw = "--quantize_weights";
const std::string cfg = "--config";
const std::string tf_maxpool = "--TF-style_maxpool";
@@ -174,6 +176,13 @@ int entry(int argc, char **argv)
"Two arguments required: source_tensor_name(string), "
"destination_tensor_name(string)");
+ arser.add_argument(qw)
+ .nargs(3)
+ .type(arser::DataType::STR_VEC)
+ .help("Quantize weights values only"
+ "Three arguments required: input_model_dtype(float32) "
+ "output_model_dtype(int8, int16) granularity(channel)");
+
arser.add_argument("--input_type")
.help("Input type of quantized model (uint8, int16, int32, int64, float32, or bool). For "
"multiple inputs, "
@@ -204,13 +213,14 @@ int entry(int argc, char **argv)
}
{
- // only one of qdqw, qwmm, rq, fq, cq, fake_quant option can be used
+ // only one of qdqw, qwmm, rq, fq, cq, fake_quant, qw option can be used
int32_t opt_used = arser[qdqw] ? 1 : 0;
opt_used += arser[qwmm] ? 1 : 0;
opt_used += arser[rq] ? 1 : 0;
opt_used += arser[fq] ? 1 : 0;
opt_used += arser[cq] ? 1 : 0;
opt_used += arser[fake_quant] ? 1 : 0;
+ opt_used += arser[qw] ? 1 : 0;
if (opt_used != 1)
{
print_exclusive_options();
@@ -368,6 +378,21 @@ int entry(int argc, char **argv)
if (arser[fake_quant])
options->enable(Algorithms::ConvertToFakeQuantizedModel);
+ if (arser[qw])
+ {
+ auto values = arser.get<std::vector<std::string>>(qw);
+ if (values.size() != 3)
+ {
+ std::cerr << arser;
+ return 255;
+ }
+ options->enable(Algorithms::QuantizeWeights);
+
+ options->param(AlgorithmParameters::Quantize_input_model_dtype, values.at(0));
+ options->param(AlgorithmParameters::Quantize_output_model_dtype, values.at(1));
+ options->param(AlgorithmParameters::Quantize_granularity, values.at(2));
+ }
+
std::string input_path = arser.get<std::string>("input");
std::string output_path = arser.get<std::string>("output");
diff --git a/compiler/circle-tensordump/CMakeLists.txt b/compiler/circle-tensordump/CMakeLists.txt
index 676aecd53..ed6ddc408 100644
--- a/compiler/circle-tensordump/CMakeLists.txt
+++ b/compiler/circle-tensordump/CMakeLists.txt
@@ -1,6 +1,6 @@
-if(NOT TARGET mio_circle04)
+if(NOT TARGET mio_circle06)
return()
-endif(NOT TARGET mio_circle04)
+endif(NOT TARGET mio_circle06)
nnas_find_package(HDF5 COMPONENTS STATIC QUIET)
@@ -19,8 +19,8 @@ target_include_directories(circle-tensordump PRIVATE ${HDF5_INCLUDE_DIRS})
target_link_libraries(circle-tensordump PRIVATE ${HDF5_CXX_LIBRARIES})
target_link_libraries(circle-tensordump PRIVATE arser)
target_link_libraries(circle-tensordump PRIVATE foder)
-target_link_libraries(circle-tensordump PRIVATE mio_circle04)
-target_link_libraries(circle-tensordump PRIVATE mio_circle04_helper)
+target_link_libraries(circle-tensordump PRIVATE mio_circle06)
+target_link_libraries(circle-tensordump PRIVATE mio_circle06_helper)
target_link_libraries(circle-tensordump PRIVATE safemain)
install(TARGETS circle-tensordump DESTINATION bin)
diff --git a/compiler/circle-tensordump/requires.cmake b/compiler/circle-tensordump/requires.cmake
index 183dfe227..b3a2638ef 100644
--- a/compiler/circle-tensordump/requires.cmake
+++ b/compiler/circle-tensordump/requires.cmake
@@ -1,4 +1,4 @@
require("arser")
require("foder")
-require("mio-circle04")
+require("mio-circle06")
require("safemain")
diff --git a/compiler/circle-tensordump/src/Dump.cpp b/compiler/circle-tensordump/src/Dump.cpp
index 49afa73df..98cb5aea2 100644
--- a/compiler/circle-tensordump/src/Dump.cpp
+++ b/compiler/circle-tensordump/src/Dump.cpp
@@ -185,6 +185,10 @@ H5::PredType hdf5_dtype_cast(const circle::TensorType &circle_type)
{
return H5::PredType::NATIVE_UINT8;
}
+ case circle::TensorType_INT8:
+ {
+ return H5::PredType::NATIVE_INT8;
+ }
case circle::TensorType_INT16:
{
return H5::PredType::NATIVE_INT16;
diff --git a/compiler/circle-verify/CMakeLists.txt b/compiler/circle-verify/CMakeLists.txt
index 5d0eb9468..cdf74cc26 100644
--- a/compiler/circle-verify/CMakeLists.txt
+++ b/compiler/circle-verify/CMakeLists.txt
@@ -1,14 +1,14 @@
-if(NOT TARGET mio_circle04)
- message(STATUS "Skip circle-verify: mio_circle04 not found")
+if(NOT TARGET mio_circle06)
+ message(STATUS "Skip circle-verify: mio_circle06 not found")
return()
-endif(NOT TARGET mio_circle04)
+endif(NOT TARGET mio_circle06)
file(GLOB_RECURSE SOURCES "src/*.cpp")
add_executable(circle-verify ${SOURCES})
target_include_directories(circle-verify PRIVATE src)
target_link_libraries(circle-verify arser)
-target_link_libraries(circle-verify mio_circle04)
+target_link_libraries(circle-verify mio_circle06)
target_link_libraries(circle-verify safemain)
target_link_libraries(circle-verify cwrap)
target_link_libraries(circle-verify foder)
diff --git a/compiler/circle-verify/requires.cmake b/compiler/circle-verify/requires.cmake
index 74c8f448b..2fd44ad75 100644
--- a/compiler/circle-verify/requires.cmake
+++ b/compiler/circle-verify/requires.cmake
@@ -1,5 +1,5 @@
require("arser")
-require("mio-circle04")
+require("mio-circle06")
require("safemain")
require("cwrap")
require("foder")
diff --git a/compiler/circle2circle-dredd-recipe-test/test.lst b/compiler/circle2circle-dredd-recipe-test/test.lst
index 4fb1e78d2..2dd24af60 100644
--- a/compiler/circle2circle-dredd-recipe-test/test.lst
+++ b/compiler/circle2circle-dredd-recipe-test/test.lst
@@ -54,6 +54,9 @@ Add(MaxPoolWithArgmax_001 PASS resolve_customop_max_pool_with_argmax)
Add(MaxPoolWithArgmax_002 PASS resolve_customop_max_pool_with_argmax)
Add(FullyConnected_007 PASS replace_non_const_fc_with_batch_matmul)
Add(FullyConnected_008 PASS replace_non_const_fc_with_batch_matmul)
+Add(Net_Gelu_000 PASS fuse_gelu)
+Add(Net_Gelu_001 PASS fuse_gelu)
+Add(HardSwish_001 PASS decompose_hardswish)
## CIRCLE RECIPE
@@ -89,3 +92,6 @@ Add(REGRESS_ONNX_Conv_BN_MeanMean_001 PASS
fuse_activation_function
fuse_mean_with_mean
fuse_transpose_with_mean)
+
+Add(REGRESS_ONNX_Mul_Mul_000 PASS
+ convert_nchw_to_nhwc)
diff --git a/compiler/circle2circle/src/Circle2Circle.cpp b/compiler/circle2circle/src/Circle2Circle.cpp
index 9afb67d85..6a7be2204 100644
--- a/compiler/circle2circle/src/Circle2Circle.cpp
+++ b/compiler/circle2circle/src/Circle2Circle.cpp
@@ -16,6 +16,7 @@
#include <luci/ImporterEx.h>
#include <luci/CircleOptimizer.h>
+#include <luci/DynamicBatchToSingleBatch.h>
#include <luci/Service/ChangeOutputs.h>
#include <luci/Service/Validate.h>
#include <luci/CircleExporter.h>
@@ -111,6 +112,7 @@ int entry(int argc, char **argv)
add_switch(arser, "--fuse_preactivation_batchnorm",
"This will fuse BatchNorm operators of pre-activations to Convolution operator");
add_switch(arser, "--fuse_prelu", "This will fuse operators to PReLU operator");
+ add_switch(arser, "--fuse_gelu", "This will fuse operators to GeLU operator");
add_switch(arser, "--remove_duplicate_const", "This will remove all duplicate constant nodes");
add_switch(arser, "--remove_fakequant", "This will remove FakeQuant operators");
add_switch(arser, "--remove_quantdequant", "This will remove Quantize-Dequantize sequence");
@@ -167,11 +169,19 @@ int entry(int argc, char **argv)
"Transform Minimum(6)-Maximum(0) pattern to Relu6 operator");
add_switch(arser, "--transform_min_relu_to_relu6",
"Transform Minimum(6)-Relu pattern to Relu6 operator");
+ add_switch(arser, "--decompose_hardswish",
+ "Decompose HardSwish operator to Add, Mul and Relu6 operators");
add_switch(arser, "--mute_warnings", "This will turn off warning messages");
add_switch(arser, "--disable_validation",
"This will turn off operator validations. May help input model investigation.");
add_switch(arser, "--generate_profile_data", "This will turn on profiling data generation.");
+ // Convert dynamic batch to single batch
+ // Users have to use this option only when the first dimension of rank 4 input (NHWC or NCHW)
+ // is dynamic. Remove this comment after non-rank 4 is supported.
+ add_switch(arser, "--dynamic_batch_to_single_batch",
+ "Convert dynamic batch size (first dimension) of inputs to 1.");
+
arser.add_argument("--change_outputs")
.help("Experimental: Change first subgraph output nodes to CSV names");
@@ -257,6 +267,8 @@ int entry(int argc, char **argv)
options->enable(Algorithms::FusePreActivationBatchNorm);
if (arser.get<bool>("--fuse_prelu"))
options->enable(Algorithms::FusePRelu);
+ if (arser.get<bool>("--fuse_gelu"))
+ options->enable(Algorithms::FuseGelu);
if (arser.get<bool>("--fuse_transpose_with_mean"))
options->enable(Algorithms::FuseTransposeWithMean);
if (arser.get<bool>("--remove_duplicate_const"))
@@ -313,6 +325,8 @@ int entry(int argc, char **argv)
options->enable(Algorithms::TransformMinMaxToRelu6Pass);
if (arser.get<bool>("--transform_min_relu_to_relu6"))
options->enable(Algorithms::TransformMinReluToRelu6Pass);
+ if (arser.get<bool>("--decompose_hardswish"))
+ options->enable(Algorithms::DecomposeHardSwishPass);
if (arser.get<bool>("--expand_broadcast_const"))
options->enable(Algorithms::ExpandBroadcastConst);
if (arser.get<bool>("--unroll_unidirseqlstm"))
@@ -368,12 +382,40 @@ int entry(int argc, char **argv)
csv_tokenize(csv_nodes, new_outputs);
}
+ bool dynamic_batch_to_single_batch = false;
+ if (arser.get<bool>("--dynamic_batch_to_single_batch"))
+ {
+ dynamic_batch_to_single_batch = true;
+ }
+
// Import from input Circle file
luci::ImporterEx importerex;
auto module = importerex.importVerifyModule(input_path);
if (module.get() == nullptr)
return EXIT_FAILURE;
+ // Convert dynamic batch to single batch
+ // Why here? It has to be done before 'optimize', because most optimization
+ // passes are written based on static shapes
+ if (dynamic_batch_to_single_batch)
+ {
+ luci::dynamic_batch_to_single_batch(module.get());
+
+ if (!luci::validate_shape(module.get()))
+ {
+ if (settings->get(luci::UserSettings::Key::DisableValidation))
+ std::cerr
+ << "WARNING: Invalid shape detected after converting dynamic batch to single batch"
+ << std::endl;
+ else
+ {
+ std::cerr << "ERROR: Invalid shape detected after converting dynamic batch to single batch"
+ << std::endl;
+ return 255;
+ }
+ }
+ }
+
if (change_outputs)
{
auto graph = module->graph(0);
diff --git a/compiler/circlechef/CMakeLists.txt b/compiler/circlechef/CMakeLists.txt
index b124d3027..56c501c24 100644
--- a/compiler/circlechef/CMakeLists.txt
+++ b/compiler/circlechef/CMakeLists.txt
@@ -5,10 +5,10 @@ if(NOT Protobuf_FOUND)
return()
endif(NOT Protobuf_FOUND)
-if(NOT TARGET mio_circle04)
- message(STATUS "circlechef: SKIP (missing mio-circle04)")
+if(NOT TARGET mio_circle06)
+ message(STATUS "circlechef: SKIP (missing mio-circle06)")
return()
-endif(NOT TARGET mio_circle04)
+endif(NOT TARGET mio_circle06)
# Recipe Parser
add_subdirectory(proto)
diff --git a/compiler/circlechef/circle/CMakeLists.txt b/compiler/circlechef/circle/CMakeLists.txt
index 12dc7217b..cdd6040b7 100644
--- a/compiler/circlechef/circle/CMakeLists.txt
+++ b/compiler/circlechef/circle/CMakeLists.txt
@@ -4,7 +4,7 @@ add_library(circlechef_circle STATIC ${SOURCES})
target_include_directories(circlechef_circle PUBLIC include)
target_include_directories(circlechef_circle PRIVATE src)
target_link_libraries(circlechef_circle circlechef_proto)
-target_link_libraries(circlechef_circle mio_circle04)
-target_link_libraries(circlechef_circle mio_circle04_helper)
+target_link_libraries(circlechef_circle mio_circle06)
+target_link_libraries(circlechef_circle mio_circle06_helper)
target_link_libraries(circlechef_circle cwrap)
target_link_libraries(circlechef_circle souschef)
diff --git a/compiler/circlechef/core/CMakeLists.txt b/compiler/circlechef/core/CMakeLists.txt
index 415954767..dc1dbc4dc 100644
--- a/compiler/circlechef/core/CMakeLists.txt
+++ b/compiler/circlechef/core/CMakeLists.txt
@@ -7,7 +7,7 @@ target_include_directories(circlechef_core PUBLIC include)
target_include_directories(circlechef_core PRIVATE src)
target_link_libraries(circlechef_core PUBLIC circlechef_proto)
target_link_libraries(circlechef_core PUBLIC circlechef_log)
-target_link_libraries(circlechef_core PUBLIC mio_circle04)
+target_link_libraries(circlechef_core PUBLIC mio_circle06)
target_link_libraries(circlechef_core PUBLIC souschef)
target_link_libraries(circlechef_core PRIVATE nncc_coverage)
diff --git a/compiler/circlechef/requires.cmake b/compiler/circlechef/requires.cmake
index a5d6bedaa..67eaa278c 100644
--- a/compiler/circlechef/requires.cmake
+++ b/compiler/circlechef/requires.cmake
@@ -1,7 +1,7 @@
require("arser")
require("nnkit")
require("cwrap")
-require("mio-circle04")
+require("mio-circle06")
require("safemain")
require("hermes")
require("hermes-std")
diff --git a/compiler/circledump/CMakeLists.txt b/compiler/circledump/CMakeLists.txt
index 7485ff8e7..b7326730a 100644
--- a/compiler/circledump/CMakeLists.txt
+++ b/compiler/circledump/CMakeLists.txt
@@ -1,7 +1,7 @@
-if(NOT TARGET mio_circle04)
- message(STATUS "Skip circledump: mio_circle04 not found")
+if(NOT TARGET mio_circle06)
+ message(STATUS "Skip circledump: mio_circle06 not found")
return()
-endif(NOT TARGET mio_circle04)
+endif(NOT TARGET mio_circle06)
set(DRIVER "driver/Driver.cpp")
@@ -11,8 +11,8 @@ add_executable(circledump ${DRIVER} ${SOURCES})
target_include_directories(circledump PRIVATE include)
target_link_libraries(circledump arser)
target_link_libraries(circledump foder)
-target_link_libraries(circledump mio_circle04)
-target_link_libraries(circledump mio_circle04_helper)
+target_link_libraries(circledump mio_circle06)
+target_link_libraries(circledump mio_circle06_helper)
target_link_libraries(circledump safemain)
install(TARGETS circledump DESTINATION bin)
diff --git a/compiler/circledump/README.md b/compiler/circledump/README.md
index d2baf26b3..f71194b08 100644
--- a/compiler/circledump/README.md
+++ b/compiler/circledump/README.md
@@ -65,6 +65,6 @@ O T(3) ofm
### Dependency
-- mio-circle04
+- mio-circle06
- safemain
- FlatBuffers
diff --git a/compiler/circledump/requires.cmake b/compiler/circledump/requires.cmake
index 183dfe227..b3a2638ef 100644
--- a/compiler/circledump/requires.cmake
+++ b/compiler/circledump/requires.cmake
@@ -1,4 +1,4 @@
require("arser")
require("foder")
-require("mio-circle04")
+require("mio-circle06")
require("safemain")
diff --git a/compiler/circledump/src/MetadataPrinter.h b/compiler/circledump/src/MetadataPrinter.h
index 1dca2ca1e..39d92c812 100644
--- a/compiler/circledump/src/MetadataPrinter.h
+++ b/compiler/circledump/src/MetadataPrinter.h
@@ -29,6 +29,7 @@ class MetadataPrinter
{
public:
virtual void print(const uint8_t * /* buffer */, std::ostream &) const = 0;
+ virtual ~MetadataPrinter() = default;
};
class MetadataPrinterRegistry
diff --git a/compiler/circledump/src/OpPrinter.cpp b/compiler/circledump/src/OpPrinter.cpp
index 817371dcf..bfcb1ec18 100644
--- a/compiler/circledump/src/OpPrinter.cpp
+++ b/compiler/circledump/src/OpPrinter.cpp
@@ -364,6 +364,22 @@ public:
}
};
+class GeluPrinter : public OpPrinter
+{
+public:
+ void options(const circle::Operator *op, std::ostream &os) const override
+ {
+ if (auto *params = op->builtin_options_as_GeluOptions())
+ {
+ os << " ";
+ os << std::boolalpha;
+ os << "approximate(" << params->approximate() << ") ";
+ os << std::noboolalpha;
+ os << std::endl;
+ }
+ }
+};
+
class IfPrinter : public OpPrinter
{
public:
@@ -643,12 +659,14 @@ class TransposeConvPrinter : public OpPrinter
public:
void options(const circle::Operator *op, std::ostream &os) const override
{
- if (auto conv_params = op->builtin_options_as_TransposeConvOptions())
+ if (auto params = op->builtin_options_as_TransposeConvOptions())
{
os << " ";
- os << "Padding(" << conv_params->padding() << ") ";
- os << "Stride.W(" << conv_params->stride_w() << ") ";
- os << "Stride.H(" << conv_params->stride_h() << ") ";
+ os << "Padding(" << params->padding() << ") ";
+ os << "Stride.W(" << params->stride_w() << ") ";
+ os << "Stride.H(" << params->stride_h() << ") ";
+ os << "Activation(" << EnumNameActivationFunctionType(params->fused_activation_function())
+ << ") ";
os << std::endl;
}
}
@@ -813,6 +831,7 @@ OpPrinterRegistry::OpPrinterRegistry()
// There is no Option for FLOOR_MOD
_op_map[circle::BuiltinOperator_FULLY_CONNECTED] = make_unique<FullyConnectedPrinter>();
_op_map[circle::BuiltinOperator_GATHER] = make_unique<GatherPrinter>();
+ _op_map[circle::BuiltinOperator_GELU] = make_unique<GeluPrinter>();
_op_map[circle::BuiltinOperator_IF] = make_unique<IfPrinter>();
_op_map[circle::BuiltinOperator_L2_NORMALIZATION] = make_unique<L2NormPrinter>();
_op_map[circle::BuiltinOperator_L2_POOL_2D] = make_unique<Pool2DPrinter>();
diff --git a/compiler/common-artifacts/CMakeLists.txt b/compiler/common-artifacts/CMakeLists.txt
index 7d89d455e..2b032034a 100644
--- a/compiler/common-artifacts/CMakeLists.txt
+++ b/compiler/common-artifacts/CMakeLists.txt
@@ -17,30 +17,17 @@ if(${PYTHON_VERSION_MINOR} LESS 8)
return()
endif()
-# Create python virtual environment with tensorflow 2.8.0
-set(VIRTUALENV_OVERLAY_TF_2_8_0 "${NNCC_OVERLAY_DIR}/venv_2_8_0")
-# TensorFlow 2.10.1 for Ubuntu22.04
-if(ONE_UBUNTU_CODENAME_JAMMY)
- set(VIRTUALENV_OVERLAY_TF_2_10_1 "${NNCC_OVERLAY_DIR}/venv_2_10_1")
-endif(ONE_UBUNTU_CODENAME_JAMMY)
+# Create python virtual environment with tensorflow 2.12.1
+set(VIRTUALENV_OVERLAY_TF_2_12_1 "${NNCC_OVERLAY_DIR}/venv_2_12_1")
add_custom_command(
- OUTPUT ${VIRTUALENV_OVERLAY_TF_2_8_0}
- COMMAND ${PYTHON_EXECUTABLE} -m venv ${VIRTUALENV_OVERLAY_TF_2_8_0}
+ OUTPUT ${VIRTUALENV_OVERLAY_TF_2_12_1}
+ COMMAND ${PYTHON_EXECUTABLE} -m venv ${VIRTUALENV_OVERLAY_TF_2_12_1}
)
# Create requirements.txt and install required pip packages
set(REQUIREMENTS_FILE "requirements.txt")
-set(REQUIREMENTS_OVERLAY_PATH_TF_2_8_0 "${VIRTUALENV_OVERLAY_TF_2_8_0}/${REQUIREMENTS_FILE}")
-
-if(ONE_UBUNTU_CODENAME_JAMMY)
- add_custom_command(
- OUTPUT ${VIRTUALENV_OVERLAY_TF_2_10_1}
- COMMAND ${PYTHON_EXECUTABLE} -m venv ${VIRTUALENV_OVERLAY_TF_2_10_1}
- )
- set(REQUIREMENTS_FILE "requirements.txt")
- set(REQUIREMENTS_OVERLAY_PATH_TF_2_10_1 "${VIRTUALENV_OVERLAY_TF_2_10_1}/${REQUIREMENTS_FILE}")
-endif(ONE_UBUNTU_CODENAME_JAMMY)
+set(REQUIREMENTS_OVERLAY_PATH_TF_2_12_1 "${VIRTUALENV_OVERLAY_TF_2_12_1}/${REQUIREMENTS_FILE}")
set(PYTHON_OVERLAY python3)
if(PYTHON_EXECUTABLE MATCHES python3.8)
@@ -53,47 +40,41 @@ if(DEFINED ENV{ONE_PIP_OPTION_TRUST_HOST})
set(PIP_OPTION_TRUSTED_HOST --trusted-host pypi.python.org --trusted-host files.pythonhosted.org --trusted-host pypi.org)
endif()
-# NOTE refer https://github.com/protocolbuffers/protobuf/issues/10051
-# TODO remove protobuf==3.20.1 when issue is resolved
-add_custom_command(
- OUTPUT ${REQUIREMENTS_OVERLAY_PATH_TF_2_8_0}
- COMMAND ${CMAKE_COMMAND} -E remove -f ${REQUIREMENTS_OVERLAY_PATH_TF_2_8_0}
- COMMAND ${CMAKE_COMMAND} -E echo "tensorflow-cpu==2.8.0" >> ${REQUIREMENTS_OVERLAY_PATH_TF_2_8_0}
- COMMAND ${CMAKE_COMMAND} -E echo "flatbuffers==1.12" >> ${REQUIREMENTS_OVERLAY_PATH_TF_2_8_0}
- COMMAND ${CMAKE_COMMAND} -E echo "protobuf==3.20.1" >> ${REQUIREMENTS_OVERLAY_PATH_TF_2_8_0}
- COMMAND ${CMAKE_COMMAND} -E echo "pydot==1.4.2" >> ${REQUIREMENTS_OVERLAY_PATH_TF_2_8_0}
- COMMAND ${VIRTUALENV_OVERLAY_TF_2_8_0}/bin/${PYTHON_OVERLAY} -m pip --default-timeout=1000
- ${PIP_OPTION_TRUSTED_HOST} install --upgrade pip setuptools
- COMMAND ${VIRTUALENV_OVERLAY_TF_2_8_0}/bin/${PYTHON_OVERLAY} -m pip --default-timeout=1000
- ${PIP_OPTION_TRUSTED_HOST} install -r ${REQUIREMENTS_OVERLAY_PATH_TF_2_8_0} --upgrade
- DEPENDS ${VIRTUALENV_OVERLAY_TF_2_8_0}
-)
-
-add_custom_target(common_artifacts_python_deps ALL
- DEPENDS ${VIRTUALENV_OVERLAY_TF_2_8_0}
- ${REQUIREMENTS_OVERLAY_PATH_TF_2_8_0}
-)
-
-if(ONE_UBUNTU_CODENAME_JAMMY)
+if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "aarch64")
+ # NOTE `tensorflow-cpu` package is not available for aarch64, so we use `tensorflow` package.
add_custom_command(
- OUTPUT ${REQUIREMENTS_OVERLAY_PATH_TF_2_10_1}
- COMMAND ${CMAKE_COMMAND} -E remove -f ${REQUIREMENTS_OVERLAY_PATH_TF_2_10_1}
- COMMAND ${CMAKE_COMMAND} -E echo "tensorflow-cpu==2.10.1" >> ${REQUIREMENTS_OVERLAY_PATH_TF_2_10_1}
- COMMAND ${CMAKE_COMMAND} -E echo "flatbuffers==23.1.21" >> ${REQUIREMENTS_OVERLAY_PATH_TF_2_10_1}
- COMMAND ${CMAKE_COMMAND} -E echo "protobuf==3.19.6" >> ${REQUIREMENTS_OVERLAY_PATH_TF_2_10_1}
- COMMAND ${CMAKE_COMMAND} -E echo "pydot==1.4.2" >> ${REQUIREMENTS_OVERLAY_PATH_TF_2_10_1}
- COMMAND ${VIRTUALENV_OVERLAY_TF_2_10_1}/bin/${PYTHON_OVERLAY} -m pip --default-timeout=1000
+ OUTPUT ${REQUIREMENTS_OVERLAY_PATH_TF_2_12_1}
+ COMMAND ${CMAKE_COMMAND} -E remove -f ${REQUIREMENTS_OVERLAY_PATH_TF_2_12_1}
+ COMMAND ${CMAKE_COMMAND} -E echo "tensorflow==2.12.1" >> ${REQUIREMENTS_OVERLAY_PATH_TF_2_12_1}
+ COMMAND ${CMAKE_COMMAND} -E echo "flatbuffers==23.5.26" >> ${REQUIREMENTS_OVERLAY_PATH_TF_2_12_1}
+ COMMAND ${CMAKE_COMMAND} -E echo "protobuf==4.23.3" >> ${REQUIREMENTS_OVERLAY_PATH_TF_2_12_1}
+ COMMAND ${CMAKE_COMMAND} -E echo "pydot==1.4.2" >> ${REQUIREMENTS_OVERLAY_PATH_TF_2_12_1}
+ COMMAND ${VIRTUALENV_OVERLAY_TF_2_12_1}/bin/${PYTHON_OVERLAY} -m pip --default-timeout=1000
${PIP_OPTION_TRUSTED_HOST} install --upgrade pip setuptools
- COMMAND ${VIRTUALENV_OVERLAY_TF_2_10_1}/bin/${PYTHON_OVERLAY} -m pip --default-timeout=1000
- ${PIP_OPTION_TRUSTED_HOST} install -r ${REQUIREMENTS_OVERLAY_PATH_TF_2_10_1} --upgrade
- DEPENDS ${VIRTUALENV_OVERLAY_TF_2_10_1}
+ COMMAND ${VIRTUALENV_OVERLAY_TF_2_12_1}/bin/${PYTHON_OVERLAY} -m pip --default-timeout=1000
+ ${PIP_OPTION_TRUSTED_HOST} install -r ${REQUIREMENTS_OVERLAY_PATH_TF_2_12_1} --upgrade
+ DEPENDS ${VIRTUALENV_OVERLAY_TF_2_12_1}
)
-
- add_custom_target(common_artifacts_python_u22_deps ALL
- DEPENDS ${VIRTUALENV_OVERLAY_TF_2_10_1}
- ${REQUIREMENTS_OVERLAY_PATH_TF_2_10_1}
+else(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "aarch64")
+ add_custom_command(
+ OUTPUT ${REQUIREMENTS_OVERLAY_PATH_TF_2_12_1}
+ COMMAND ${CMAKE_COMMAND} -E remove -f ${REQUIREMENTS_OVERLAY_PATH_TF_2_12_1}
+ COMMAND ${CMAKE_COMMAND} -E echo "tensorflow-cpu==2.12.1" >> ${REQUIREMENTS_OVERLAY_PATH_TF_2_12_1}
+ COMMAND ${CMAKE_COMMAND} -E echo "flatbuffers==23.5.26" >> ${REQUIREMENTS_OVERLAY_PATH_TF_2_12_1}
+ COMMAND ${CMAKE_COMMAND} -E echo "protobuf==4.23.3" >> ${REQUIREMENTS_OVERLAY_PATH_TF_2_12_1}
+ COMMAND ${CMAKE_COMMAND} -E echo "pydot==1.4.2" >> ${REQUIREMENTS_OVERLAY_PATH_TF_2_12_1}
+ COMMAND ${VIRTUALENV_OVERLAY_TF_2_12_1}/bin/${PYTHON_OVERLAY} -m pip --default-timeout=1000
+ ${PIP_OPTION_TRUSTED_HOST} install --upgrade pip setuptools
+ COMMAND ${VIRTUALENV_OVERLAY_TF_2_12_1}/bin/${PYTHON_OVERLAY} -m pip --default-timeout=1000
+ ${PIP_OPTION_TRUSTED_HOST} install -r ${REQUIREMENTS_OVERLAY_PATH_TF_2_12_1} --upgrade
+ DEPENDS ${VIRTUALENV_OVERLAY_TF_2_12_1}
)
-endif(ONE_UBUNTU_CODENAME_JAMMY)
+endif(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "aarch64")
+
+add_custom_target(common_artifacts_python_deps ALL
+ DEPENDS ${VIRTUALENV_OVERLAY_TF_2_12_1}
+ ${REQUIREMENTS_OVERLAY_PATH_TF_2_12_1}
+)
#[[ Generate common resources ]]
# TODO add pbtxt
diff --git a/compiler/common-artifacts/exclude.lst b/compiler/common-artifacts/exclude.lst
index f238e79eb..75055225b 100644
--- a/compiler/common-artifacts/exclude.lst
+++ b/compiler/common-artifacts/exclude.lst
@@ -70,6 +70,8 @@ tcgenerate(Net_Dangle_001)
tcgenerate(Net_Densify_Add_000) # luci-interpreter doesn't support Densify yet
tcgenerate(Net_Densify_Dequantize_Add_000) # luci-interpreter doesn't support Densify/Dequantize yet
tcgenerate(Net_Gather_SparseToDense_AddV2_000) # luci-interpreter doesn't support custom operator
+tcgenerate(Net_Gelu_000) # luci-interpreter doesn't support custom operator
+tcgenerate(Net_Gelu_001) # luci-interpreter doesn't support custom operator
tcgenerate(Net_ZeroDim_001) # luci-interpreter doesn't support zero dim
tcgenerate(OneHot_000)
tcgenerate(OneHot_001)
@@ -78,6 +80,16 @@ tcgenerate(OneHot_003)
tcgenerate(Pack_000)
tcgenerate(Pack_U8_000)
tcgenerate(PadV2_000)
+tcgenerate(Quant_Add_I8_000) # INT8 is not supported
+tcgenerate(Quant_AveragePool2D_I8_000) # INT8 is not supported
+tcgenerate(Quant_Conv_I8_000) # INT8 is not supported
+tcgenerate(Quant_DepthwiseConv2D_I8_000) # INT8 is not supported
+tcgenerate(Quant_MaxPool2D_I8_000) # INT8 is not supported
+tcgenerate(Quant_Mean_I8_000) # INT8 is not supported
+tcgenerate(Quant_Mul_I8_000) # INT8 is not supported
+tcgenerate(Quant_PRelu_I8_000) # INT8 is not supported
+tcgenerate(Quant_ReLU_I8_000) # INT8 is not supported
+tcgenerate(Quant_TransposeConv_I8_000) # INT8 is not supported
tcgenerate(Quantize_000) # runtime and luci-interpreter doesn't support Quantize op yet
tcgenerate(Range_000)
tcgenerate(Rank_000)
diff --git a/compiler/dalgona-test/CMakeLists.txt b/compiler/dalgona-test/CMakeLists.txt
index a23383152..c8b9c2597 100644
--- a/compiler/dalgona-test/CMakeLists.txt
+++ b/compiler/dalgona-test/CMakeLists.txt
@@ -53,17 +53,6 @@ add_test(
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/TestSingleOp.sh"
"${TEST_CONFIG}"
"${ARTIFACTS_BIN_PATH}"
- "${NNCC_OVERLAY_DIR}/venv_2_8_0"
+ "${NNCC_OVERLAY_DIR}/venv_2_12_1"
${DALGONA_SINGLE_OP_TEST}
)
-
-if(ONE_UBUNTU_CODENAME_JAMMY)
- add_test(
- NAME dalgona_single_op_210_test
- COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/TestSingleOp.sh"
- "${TEST_CONFIG}"
- "${ARTIFACTS_BIN_PATH}"
- "${NNCC_OVERLAY_DIR}/venv_2_10_1"
- ${DALGONA_SINGLE_OP_TEST}
- )
-endif(ONE_UBUNTU_CODENAME_JAMMY)
diff --git a/compiler/dalgona/src/Dalgona.cpp b/compiler/dalgona/src/Dalgona.cpp
index 1d060b4c4..1a35b6d03 100644
--- a/compiler/dalgona/src/Dalgona.cpp
+++ b/compiler/dalgona/src/Dalgona.cpp
@@ -163,13 +163,14 @@ void Dalgona::runAnalysisWithH5Input(const std::string &input_data_path,
if (is_raw_data)
{
// Skip type/shape check for raw data
- importer.readTensor(record_idx, input_idx, input_data.data());
+ importer.readTensor(record_idx, input_idx, input_data.data(), input_data.size());
}
else
{
DataType dtype;
Shape shape;
- importer.readTensor(record_idx, input_idx, &dtype, &shape, input_data.data());
+ importer.readTensor(record_idx, input_idx, &dtype, &shape, input_data.data(),
+ input_data.size());
// Check the type and the shape of the input data is valid
verifyTypeShape(input_node, dtype, shape);
diff --git a/compiler/dalgona/src/PostOperatorHook.h b/compiler/dalgona/src/PostOperatorHook.h
index daf32f693..00c5d461c 100644
--- a/compiler/dalgona/src/PostOperatorHook.h
+++ b/compiler/dalgona/src/PostOperatorHook.h
@@ -42,6 +42,7 @@ class PostOperatorHook final : public luci::CircleNodeVisitor<void>
// 2. inputs: input data (type: std::vector of numpy array)
// 3. output: output data (type: numpy array)
#define POST_OPERATOR_HOOK_PROLOGUE(OP_NAME) \
+ assert(not multi_out_node(node)); \
if (!py::hasattr(_analysis, #OP_NAME "Post")) \
{ \
visit(loco::must_cast<const luci::CircleNode *>(node)); \
@@ -53,6 +54,7 @@ class PostOperatorHook final : public luci::CircleNodeVisitor<void>
// Multi-output version of POST_OPERATOR_HOOK_PROLOGUE
#define POST_OPERATOR_HOOK_PROLOGUE_MULTI_OUTS(OP_NAME) \
+ assert(multi_out_node(node)); \
if (!py::hasattr(_analysis, #OP_NAME "Post")) \
{ \
visit(loco::must_cast<const luci::CircleNode *>(node)); \
@@ -81,7 +83,6 @@ public:
py::object hook = _analysis.attr("DefaultOpPost");
auto inputs = inputsPyArray(node, _interpreter);
- auto output = outputPyArray(node, _interpreter);
py::list input_list;
for (uint32_t i = 0; i < inputs.size(); i++)
@@ -89,11 +90,26 @@ public:
input_list.append(inputs[i]);
}
+ py::list output_list;
+ if (multi_out_node(node))
+ {
+ auto outputs = outputsPyArray(node, _interpreter);
+ for (uint32_t i = 0; i < outputs.size(); i++)
+ {
+ output_list.append(outputs[i]);
+ }
+ }
+ else
+ {
+ auto output = outputPyArray(node, _interpreter);
+ output_list.append(output);
+ }
+
pySafeCall(hook,
node->name(), // name
toString(node->opcode()), // opcode
input_list, // list of inputs
- output // output
+ output_list // list of outputs
);
}
diff --git a/compiler/dalgona/src/Utils.cpp b/compiler/dalgona/src/Utils.cpp
index f65d9c24c..a5b0bb529 100644
--- a/compiler/dalgona/src/Utils.cpp
+++ b/compiler/dalgona/src/Utils.cpp
@@ -170,6 +170,28 @@ py::dict outputPyArray(const luci::CircleNode *node, luci_interpreter::Interpret
return py_output;
}
+bool multi_out_node(const luci::CircleNode *node)
+{
+ switch (node->opcode())
+ {
+ // TODO Update this list when new Op is added
+ // Tip: grep "public GraphBuilderMultiOutput" in luci/import
+ case luci::CircleOpcode::BIDIRECTIONAL_SEQUENCE_LSTM:
+ case luci::CircleOpcode::CUSTOM:
+ case luci::CircleOpcode::IF:
+ case luci::CircleOpcode::NON_MAX_SUPPRESSION_V4:
+ case luci::CircleOpcode::NON_MAX_SUPPRESSION_V5:
+ case luci::CircleOpcode::SPLIT:
+ case luci::CircleOpcode::SPLIT_V:
+ case luci::CircleOpcode::TOPK_V2:
+ case luci::CircleOpcode::UNIQUE:
+ case luci::CircleOpcode::UNPACK:
+ return true;
+ default:
+ return false;
+ }
+}
+
} // namespace dalgona
#undef THROW_UNLESS
diff --git a/compiler/dalgona/src/Utils.h b/compiler/dalgona/src/Utils.h
index 9ca920f25..7bda30745 100644
--- a/compiler/dalgona/src/Utils.h
+++ b/compiler/dalgona/src/Utils.h
@@ -51,6 +51,8 @@ std::vector<py::dict> outputsPyArray(const luci::CircleNode *node,
py::object none();
+bool multi_out_node(const luci::CircleNode *node);
+
} // namespace dalgona
#endif // __DALGONA_UTILS_H__
diff --git a/compiler/dio-hdf5/include/dio_hdf5/HDF5Importer.h b/compiler/dio-hdf5/include/dio_hdf5/HDF5Importer.h
index aafcfbbf3..add441147 100644
--- a/compiler/dio-hdf5/include/dio_hdf5/HDF5Importer.h
+++ b/compiler/dio-hdf5/include/dio_hdf5/HDF5Importer.h
@@ -58,12 +58,13 @@ public:
* @param dtype : pointer to write the tensor's data type
* @param shape : pointer to write the tensor's shape
* @param buffer : pointer to write the tensor's data
+ * @param buffer_bytes : byte size of the buffer
*/
void readTensor(int32_t data_idx, int32_t input_idx, loco::DataType *dtype,
- std::vector<loco::Dimension> *shape, void *buffer);
+ std::vector<loco::Dimension> *shape, void *buffer, size_t buffer_bytes);
// Read a raw tensor (no type/shape is specified)
- void readTensor(int32_t data_idx, int32_t input_idx, void *buffer);
+ void readTensor(int32_t data_idx, int32_t input_idx, void *buffer, size_t buffer_bytes);
bool isRawData() { return _group.attrExists("rawData"); }
diff --git a/compiler/dio-hdf5/src/HDF5Importer.cpp b/compiler/dio-hdf5/src/HDF5Importer.cpp
index 9ae556b77..920899058 100644
--- a/compiler/dio-hdf5/src/HDF5Importer.cpp
+++ b/compiler/dio-hdf5/src/HDF5Importer.cpp
@@ -128,16 +128,20 @@ int32_t HDF5Importer::numInputs(int32_t record_idx)
return records.getNumObjs();
}
-void HDF5Importer::readTensor(int32_t record_idx, int32_t input_idx, void *buffer)
+void HDF5Importer::readTensor(int32_t record_idx, int32_t input_idx, void *buffer,
+ size_t buffer_bytes)
{
auto record = _group.openGroup(std::to_string(record_idx));
auto tensor = record.openDataSet(std::to_string(input_idx));
+ if (tensor.getInMemDataSize() != buffer_bytes)
+ throw std::runtime_error("Buffer size does not match with the size of tensor data");
+
readTensorData(tensor, static_cast<uint8_t *>(buffer));
}
void HDF5Importer::readTensor(int32_t record_idx, int32_t input_idx, DataType *dtype, Shape *shape,
- void *buffer)
+ void *buffer, size_t buffer_bytes)
{
auto record = _group.openGroup(std::to_string(record_idx));
auto tensor = record.openDataSet(std::to_string(input_idx));
@@ -148,6 +152,9 @@ void HDF5Importer::readTensor(int32_t record_idx, int32_t input_idx, DataType *d
auto tensor_shape = tensor.getSpace();
*shape = toInternalShape(tensor_shape);
+ if (tensor.getInMemDataSize() != buffer_bytes)
+ throw std::runtime_error("Buffer size does not match with the size of tensor data");
+
switch (*dtype)
{
case DataType::FLOAT32:
diff --git a/compiler/dio-hdf5/src/HDF5Importer.test.cpp b/compiler/dio-hdf5/src/HDF5Importer.test.cpp
index 61a027fc5..1433e761d 100644
--- a/compiler/dio-hdf5/src/HDF5Importer.test.cpp
+++ b/compiler/dio-hdf5/src/HDF5Importer.test.cpp
@@ -73,7 +73,7 @@ TEST(dio_hdf5_test, read_with_type_shape)
DataType dtype;
Shape shape;
- h5.readTensor(0, 0, &dtype, &shape, buffer.data());
+ h5.readTensor(0, 0, &dtype, &shape, buffer.data(), buffer.size() * sizeof(float));
for (uint32_t i = 0; i < 6; i++)
EXPECT_EQ(i, buffer[i]);
@@ -114,7 +114,8 @@ TEST(dio_hdf5_test, data_out_of_index_NEG)
DataType dtype;
Shape shape;
// Read non-existing data (data_idx = 1)
- EXPECT_ANY_THROW(h5.readTensor(1, 0, &dtype, &shape, buffer.data()));
+ EXPECT_ANY_THROW(
+ h5.readTensor(1, 0, &dtype, &shape, buffer.data(), buffer.size() * sizeof(float)));
}
TEST(dio_hdf5_test, input_out_of_index_NEG)
@@ -130,5 +131,21 @@ TEST(dio_hdf5_test, input_out_of_index_NEG)
DataType dtype;
Shape shape;
// Read non-existing input (input_idx = 1)
- EXPECT_ANY_THROW(h5.readTensor(0, 1, &dtype, &shape, buffer.data()));
+ EXPECT_ANY_THROW(
+ h5.readTensor(0, 1, &dtype, &shape, buffer.data(), buffer.size() * sizeof(float)));
+}
+
+TEST(dio_hdf5_test, wrong_buffer_size_NEG)
+{
+ createFile();
+
+ HDF5Importer h5(::file_name);
+
+ h5.importGroup("value");
+
+ std::vector<float> buffer(6);
+
+ DataType dtype;
+ Shape shape;
+ EXPECT_ANY_THROW(h5.readTensor(0, 0, &dtype, &shape, buffer.data(), 1 /* wrong buffer size */));
}
diff --git a/compiler/loco/CMakeLists.txt b/compiler/loco/CMakeLists.txt
index 52011ec17..d885805d7 100644
--- a/compiler/loco/CMakeLists.txt
+++ b/compiler/loco/CMakeLists.txt
@@ -15,7 +15,7 @@ target_link_libraries(loco PUBLIC nncc_coverage)
# Q. HOW TO MAKE DEV PACKAGE(?)
install(TARGETS loco DESTINATION lib)
install(DIRECTORY include/ DESTINATION include
- FILES_MATCHING PATTERN "*.h")
+ FILES_MATCHING PATTERN "*.h" PATTERN "*.lst")
if(NOT ENABLE_TEST)
return()
diff --git a/compiler/luci-eval-driver/src/EvalDriver.cpp b/compiler/luci-eval-driver/src/EvalDriver.cpp
index 8d844ab30..fb48f67e2 100644
--- a/compiler/luci-eval-driver/src/EvalDriver.cpp
+++ b/compiler/luci-eval-driver/src/EvalDriver.cpp
@@ -93,7 +93,12 @@ int entry(int argc, char **argv)
// Data for n'th input is read from ${input_prefix}n
// (ex: Add.circle.input0, Add.circle.input1 ..)
const auto input_nodes = loco::input_nodes(module->graph());
- assert(num_inputs == input_nodes.size());
+ if (num_inputs != input_nodes.size())
+ {
+ // NOTE using num_inputs is actually unnecessary but is kept to preserve interface.
+ std::cerr << "ERROR: invalid num_inputs value; should be " << input_nodes.size() << std::endl;
+ return EXIT_FAILURE;
+ }
for (int32_t i = 0; i < num_inputs; i++)
{
const auto *input_node = loco::must_cast<const luci::CircleInput *>(input_nodes[i]);
diff --git a/compiler/luci-interpreter/include/luci_interpreter/core/Tensor.h b/compiler/luci-interpreter/include/luci_interpreter/core/Tensor.h
index bb9ff6d4a..ad3388785 100644
--- a/compiler/luci-interpreter/include/luci_interpreter/core/Tensor.h
+++ b/compiler/luci-interpreter/include/luci_interpreter/core/Tensor.h
@@ -166,9 +166,9 @@ private:
DataType _element_type;
Shape _shape;
AffineQuantization _quantization;
- uint8_t *_data;
+ uint8_t *_data = nullptr;
std::string _name;
- bool _data_allocated;
+ bool _data_allocated = false;
// Write of tensor is reported to registered Observers only if this tensor is observable
// This is needed for tensors used in kernel implementation, but not present in original model.
bool _is_observable = true;
diff --git a/compiler/luci-interpreter/pal/linux/KernelsToBuild.lst b/compiler/luci-interpreter/pal/linux/KernelsToBuild.lst
index db31cbfdc..e4d42de33 100644
--- a/compiler/luci-interpreter/pal/linux/KernelsToBuild.lst
+++ b/compiler/luci-interpreter/pal/linux/KernelsToBuild.lst
@@ -17,11 +17,14 @@ REGISTER_KERNEL(ExpandDims)
REGISTER_KERNEL(Fill)
REGISTER_KERNEL(Floor)
REGISTER_KERNEL(FloorDiv)
+REGISTER_KERNEL(FloorMod)
REGISTER_KERNEL(Equal)
REGISTER_KERNEL(FullyConnected)
REGISTER_KERNEL(Gather)
+REGISTER_KERNEL(Gelu)
REGISTER_KERNEL(Greater)
REGISTER_KERNEL(GreaterEqual)
+REGISTER_KERNEL(HardSwish)
REGISTER_KERNEL(If)
REGISTER_KERNEL(InstanceNorm)
REGISTER_KERNEL(L2Normalize)
@@ -30,6 +33,7 @@ REGISTER_KERNEL(LeakyRelu)
REGISTER_KERNEL(Less)
REGISTER_KERNEL(LessEqual)
REGISTER_KERNEL(LocalResponseNormalization)
+REGISTER_KERNEL(Log)
REGISTER_KERNEL(LogicalAnd)
REGISTER_KERNEL(LogicalNot)
REGISTER_KERNEL(LogicalOr)
@@ -59,6 +63,7 @@ REGISTER_KERNEL(ResizeBilinear)
REGISTER_KERNEL(ResizeNearestNeighbor)
REGISTER_KERNEL(ReverseV2)
REGISTER_KERNEL(Rsqrt)
+REGISTER_KERNEL(Select)
REGISTER_KERNEL(Shape)
REGISTER_KERNEL(Slice)
REGISTER_KERNEL(Softmax)
@@ -72,6 +77,7 @@ REGISTER_KERNEL(Square)
REGISTER_KERNEL(SquaredDifference)
REGISTER_KERNEL(Squeeze)
REGISTER_KERNEL(Sub)
+REGISTER_KERNEL(Sum)
REGISTER_KERNEL(SVDF)
REGISTER_KERNEL(Tanh)
REGISTER_KERNEL(Transpose)
diff --git a/onert-micro/luci-interpreter/pal/linux/PALElu.h b/compiler/luci-interpreter/pal/linux/PALGelu.h
index 7746d9691..e1796e727 100644
--- a/onert-micro/luci-interpreter/pal/linux/PALElu.h
+++ b/compiler/luci-interpreter/pal/linux/PALGelu.h
@@ -1,6 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,18 +14,19 @@
* limitations under the License.
*/
-#ifndef LUCI_INTERPRETER_PAL_ELU_H
-#define LUCI_INTERPRETER_PAL_ELU_H
+#ifndef LUCI_INTERPRETER_PAL_GELU_H
+#define LUCI_INTERPRETER_PAL_GELU_H
-#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
+#include <tensorflow/lite/kernels/internal/reference/gelu.h>
namespace luci_interpreter_pal
{
-static inline void Elu(const tflite::RuntimeShape &input_shape, const float *input_data,
- const tflite::RuntimeShape &output_shape, float *output_data)
+static inline void Gelu(bool approximate, const tflite::RuntimeShape &input_shape,
+ const float *input_data, const tflite::RuntimeShape &output_shape,
+ float *output_data)
{
- tflite::optimized_ops::Elu(input_shape, input_data, output_shape, output_data);
+ tflite::reference_ops::Gelu(input_shape, input_data, approximate, output_shape, output_data);
}
} // namespace luci_interpreter_pal
-#endif // LUCI_INTERPRETER_PAL_ELU_H
+#endif // LUCI_INTERPRETER_PAL_GELU_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALLeakyRelu.h b/compiler/luci-interpreter/pal/linux/PALHardSwish.h
index 506efb243..2ce7cb3a1 100644
--- a/onert-micro/luci-interpreter/pal/linux/PALLeakyRelu.h
+++ b/compiler/luci-interpreter/pal/linux/PALHardSwish.h
@@ -1,6 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,19 +14,18 @@
* limitations under the License.
*/
-#ifndef LUCI_INTERPRETER_PAL_LEAKYRELU_H
-#define LUCI_INTERPRETER_PAL_LEAKYRELU_H
+#ifndef LUCI_INTERPRETER_PAL_HARDSWISH_H
+#define LUCI_INTERPRETER_PAL_HARDSWISH_H
#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
namespace luci_interpreter_pal
{
-static inline void LeakyRelu(const tflite::LeakyReluParams &params,
- const tflite::RuntimeShape &input_shape, const float *input_data,
+static inline void HardSwish(const tflite::RuntimeShape &input_shape, const float *input_data,
const tflite::RuntimeShape &output_shape, float *output_data)
{
- tflite::optimized_ops::LeakyRelu(params, input_shape, input_data, output_shape, output_data);
+ tflite::optimized_ops::HardSwish(input_shape, input_data, output_shape, output_data);
}
} // namespace luci_interpreter_pal
-#endif // LUCI_INTERPRETER_PAL_LEAKYRELU_H
+#endif // LUCI_INTERPRETER_PAL_HARDSWISH_H
diff --git a/compiler/luci-interpreter/pal/linux/pal.cmake b/compiler/luci-interpreter/pal/linux/pal.cmake
index 185700cf9..28f6352bc 100644
--- a/compiler/luci-interpreter/pal/linux/pal.cmake
+++ b/compiler/luci-interpreter/pal/linux/pal.cmake
@@ -1,8 +1,34 @@
+# set target platform to run
+if(NOT TARGET_ARCH OR "${TARGET_ARCH}" STREQUAL "")
+ string(TOLOWER ${CMAKE_SYSTEM_PROCESSOR} TARGET_ARCH)
+else()
+ string(TOLOWER ${TARGET_ARCH} TARGET_ARCH)
+endif()
+
+# If TARGET_ARCH is arm64 change ARCH name to aarch64
+if("${TARGET_ARCH}" STREQUAL "arm64")
+ set(TARGET_ARCH "aarch64")
+endif()
+
+if("${TARGET_ARCH}" STREQUAL "armv8-m")
+ set(TARGET_ARCH_BASE "arm")
+elseif("${TARGET_ARCH}" STREQUAL "armv7-r")
+ set(TARGET_ARCH_BASE "arm")
+elseif("${TARGET_ARCH}" STREQUAL "armv7em")
+ set(TARGET_ARCH_BASE "arm")
+elseif("${TARGET_ARCH}" STREQUAL "armv7l")
+ set(TARGET_ARCH_BASE "arm")
+elseif("${TARGET_ARCH}" STREQUAL "armv7hl")
+ set(TARGET_ARCH_BASE "arm")
+elseif("${TARGET_ARCH}" STREQUAL "aarch64")
+ set(TARGET_ARCH_BASE "aarch64")
+endif()
+
macro(initialize_pal)
- nnas_find_package(TensorFlowSource EXACT 2.6.0 QUIET)
- nnas_find_package(TensorFlowGEMMLowpSource EXACT 2.6.0 QUIET)
- nnas_find_package(TensorFlowEigenSource EXACT 2.6.0 QUIET)
- nnas_find_package(TensorFlowRuySource EXACT 2.6.0 QUIET)
+ nnas_find_package(TensorFlowSource EXACT 2.8.0 QUIET)
+ nnas_find_package(TensorFlowGEMMLowpSource EXACT 2.8.0 QUIET)
+ nnas_find_package(TensorFlowEigenSource EXACT 2.8.0 QUIET)
+ nnas_find_package(TensorFlowRuySource EXACT 2.8.0 QUIET)
if (NOT TensorFlowSource_FOUND)
message(STATUS "Skipping luci-interpreter: TensorFlow not found")
@@ -44,7 +70,7 @@ macro(add_pal_to_target TGT)
${TensorFlowSource_DIR}/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.cc
${TensorFlowSource_DIR}/tensorflow/lite/kernels/internal/quantization_util.cc)
- if(BUILD_ARM32_NEON)
+ if(TARGET_ARCH_BASE STREQUAL "arm")
# NOTE may need to revise this list for version upgrade
set(PAL_SOURCES ${PAL_SOURCES}
${TensorFlowSource_DIR}/tensorflow/lite/kernels/internal/optimized/neon_tensor_utils.cc
@@ -67,7 +93,32 @@ macro(add_pal_to_target TGT)
${TensorFlowRuySource_DIR}/ruy/wait.cc
${TensorFlowRuySource_DIR}/ruy/kernel_arm32.cc
)
- endif(BUILD_ARM32_NEON)
+ endif(TARGET_ARCH_BASE STREQUAL "arm")
+
+ if(TARGET_ARCH_BASE STREQUAL "aarch64")
+ # NOTE may need to revise this list for version upgrade
+ set(PAL_SOURCES ${PAL_SOURCES}
+ ${TensorFlowSource_DIR}/tensorflow/lite/kernels/internal/optimized/neon_tensor_utils.cc
+ ${TensorFlowSource_DIR}/tensorflow/lite/kernels/internal/optimized/cpu_check.cc
+ ${TensorFlowRuySource_DIR}/ruy/allocator.cc
+ ${TensorFlowRuySource_DIR}/ruy/block_map.cc
+ ${TensorFlowRuySource_DIR}/ruy/blocking_counter.cc
+ ${TensorFlowRuySource_DIR}/ruy/context_get_ctx.cc
+ ${TensorFlowRuySource_DIR}/ruy/cpuinfo.cc
+ ${TensorFlowRuySource_DIR}/ruy/ctx.cc
+ ${TensorFlowRuySource_DIR}/ruy/denormal.cc
+ ${TensorFlowRuySource_DIR}/ruy/frontend.cc
+ ${TensorFlowRuySource_DIR}/ruy/pack_arm.cc
+ ${TensorFlowRuySource_DIR}/ruy/prepacked_cache.cc
+ ${TensorFlowRuySource_DIR}/ruy/prepare_packed_matrices.cc
+ ${TensorFlowRuySource_DIR}/ruy/system_aligned_alloc.cc
+ ${TensorFlowRuySource_DIR}/ruy/thread_pool.cc
+ ${TensorFlowRuySource_DIR}/ruy/trmul.cc
+ ${TensorFlowRuySource_DIR}/ruy/tune.cc
+ ${TensorFlowRuySource_DIR}/ruy/wait.cc
+ ${TensorFlowRuySource_DIR}/ruy/kernel_arm64.cc
+ )
+ endif(TARGET_ARCH_BASE STREQUAL "aarch64")
add_library(luci_interpreter_linux_pal STATIC ${PAL_SOURCES})
set_target_properties(luci_interpreter_linux_pal PROPERTIES POSITION_INDEPENDENT_CODE ON)
diff --git a/compiler/luci-interpreter/src/core/KernelParams.h b/compiler/luci-interpreter/src/core/KernelParams.h
index 45f3bfe0a..4ddbcefb8 100644
--- a/compiler/luci-interpreter/src/core/KernelParams.h
+++ b/compiler/luci-interpreter/src/core/KernelParams.h
@@ -98,6 +98,11 @@ struct GatherParams
int32_t batch_dims;
};
+struct GeluParams
+{
+ bool approximate;
+};
+
struct InstanceNormParams
{
float epsilon;
@@ -216,6 +221,7 @@ struct TransposeConvParams
Padding padding;
int32_t stride_height;
int32_t stride_width;
+ Activation activation;
};
struct UnidirectionalSequenceLSTMParams
diff --git a/compiler/luci-interpreter/src/kernels/FloorMod.cpp b/compiler/luci-interpreter/src/kernels/FloorMod.cpp
new file mode 100644
index 000000000..a64fcad3a
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/FloorMod.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2018 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/FloorMod.h"
+#include "kernels/Utils.h"
+
+#include <tensorflow/lite/kernels/internal/reference/binary_function.h>
+#include <cmath>
+
+namespace
+{
+
+template <typename T> T FloorDivFunc(T input1, T input2)
+{
+ struct FloatMod
+ {
+ float operator()(const float lhs, const float rhs) const { return std::fmod(lhs, rhs); }
+ };
+ using ModFunc =
+ typename std::conditional<std::is_integral<T>::value, std::modulus<T>, FloatMod>::type;
+ ModFunc mod_func;
+ T trunc_mod = mod_func(input1, input2);
+ return (trunc_mod != 0) && ((input2 < 0) != (trunc_mod < 0)) ? (trunc_mod + input2) : trunc_mod;
+}
+
+} // namespace
+
+namespace luci_interpreter
+{
+
+namespace kernels
+{
+
+FloorMod::FloorMod(const Tensor *x, const Tensor *y, Tensor *output) : Kernel({x, y}, {output}) {}
+
+void FloorMod::configure()
+{
+ LUCI_INTERPRETER_CHECK(x()->element_type() == output()->element_type());
+ LUCI_INTERPRETER_CHECK(y()->element_type() == output()->element_type());
+
+ output()->resize(calculateShapeForBroadcast(x()->shape(), y()->shape()));
+}
+
+void FloorMod::execute() const
+{
+ switch (x()->element_type())
+ {
+ case DataType::FLOAT32:
+ evalFloat();
+ break;
+ case DataType::S8:
+ evalInteger<int8_t>();
+ break;
+ case DataType::S16:
+ evalInteger<int16_t>();
+ break;
+ case DataType::S32:
+ evalInteger<int32_t>();
+ break;
+ case DataType::S64:
+ evalInteger<int64_t>();
+ break;
+ default:
+ throw std::runtime_error("Unsupported type.");
+ }
+}
+
+void FloorMod::evalFloat() const
+{
+ const auto x_data = getTensorData<float>(x());
+ const auto y_data = getTensorData<float>(y());
+
+ if (x()->shape() != y()->shape())
+ {
+ tflite::reference_ops::BroadcastBinaryFunction4DSlow<float, float, float>(
+ getTensorShape(x()), x_data, getTensorShape(y()), y_data, getTensorShape(output()),
+ getTensorData<float>(output()), FloorDivFunc<float>);
+ }
+ else
+ {
+ tflite::reference_ops::BinaryFunction<float, float, float>(
+ getTensorShape(x()), x_data, getTensorShape(y()), y_data, getTensorShape(output()),
+ getTensorData<float>(output()), FloorDivFunc<float>);
+ }
+}
+
+template <typename T> void FloorMod::evalInteger() const
+{
+ const auto x_data = getTensorData<T>(x());
+ const auto y_data = getTensorData<T>(y());
+
+ // Check the denominator
+ const auto y_data_type = y()->element_type();
+ if (y_data_type == DataType::S8 || y_data_type == DataType::S16 || y_data_type == DataType::S32 ||
+ y_data_type == DataType::S64)
+ {
+ for (int i = 0; i < getTensorShape(y()).FlatSize(); ++i)
+ {
+ LUCI_INTERPRETER_CHECK(y_data[i] != 0);
+ }
+ }
+
+ if (x()->shape() != y()->shape())
+ {
+ tflite::reference_ops::BroadcastBinaryFunction4DSlow<T, T, T>(
+ getTensorShape(x()), x_data, getTensorShape(y()), y_data, getTensorShape(output()),
+ getTensorData<T>(output()), FloorDivFunc<T>);
+ }
+ else
+ {
+ tflite::reference_ops::BinaryFunction<T, T, T>(getTensorShape(x()), x_data, getTensorShape(y()),
+ y_data, getTensorShape(output()),
+ getTensorData<T>(output()), FloorDivFunc<T>);
+ }
+}
+
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Less.h b/compiler/luci-interpreter/src/kernels/FloorMod.h
index 364e5a9b6..f2d9b2ae8 100644
--- a/onert-micro/luci-interpreter/src/kernels/Less.h
+++ b/compiler/luci-interpreter/src/kernels/FloorMod.h
@@ -1,6 +1,5 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,8 +14,8 @@
* limitations under the License.
*/
-#ifndef LUCI_INTERPRETER_KERNELS_LESS_H
-#define LUCI_INTERPRETER_KERNELS_LESS_H
+#ifndef LUCI_INTERPRETER_KERNELS_FLOOR_MOD_H
+#define LUCI_INTERPRETER_KERNELS_FLOOR_MOD_H
#include "core/Kernel.h"
@@ -25,10 +24,10 @@ namespace luci_interpreter
namespace kernels
{
-class Less : public Kernel
+class FloorMod : public Kernel
{
public:
- Less(const Tensor *x, const Tensor *y, Tensor *output);
+ FloorMod(const Tensor *x, const Tensor *y, Tensor *output);
const Tensor *x() const { return _inputs[0]; }
const Tensor *y() const { return _inputs[1]; }
@@ -40,16 +39,9 @@ public:
private:
void evalFloat() const;
template <typename T> void evalInteger() const;
- void evalQuantized() const;
-
-private:
- int32_t _x_multiplier = 0;
- int _x_shift = 0;
- int32_t _y_multiplier = 0;
- int _y_shift = 0;
};
} // namespace kernels
} // namespace luci_interpreter
-#endif // LUCI_INTERPRETER_KERNELS_LESS_H
+#endif // LUCI_INTERPRETER_KERNELS_FLOOR_MOD_H
diff --git a/compiler/luci-interpreter/src/kernels/FloorMod.test.cpp b/compiler/luci-interpreter/src/kernels/FloorMod.test.cpp
new file mode 100644
index 000000000..123a91e3a
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/FloorMod.test.cpp
@@ -0,0 +1,446 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2018 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/FloorMod.h"
+#include "kernels/TestUtils.h"
+#include "luci_interpreter/TestMemoryManager.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+namespace
+{
+
+using namespace testing;
+
+class FloorModTest : public ::testing::Test
+{
+protected:
+ void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
+
+ std::unique_ptr<IMemoryManager> _memory_manager;
+};
+
+TEST_F(FloorModTest, Simple)
+{
+ Shape input1_shape{1, 2, 2, 1};
+ std::vector<int32_t> input1_data{10, 9, 11, 3};
+
+ Shape input2_shape = input1_shape;
+ std::vector<int32_t> input2_data{2, 2, 3, 4};
+
+ std::vector<int32_t> ref_output_shape{1, 2, 2, 1};
+ std::vector<int32_t> ref_output_data{0, 1, 2, 3};
+
+ Tensor input1_tensor =
+ makeInputTensor<DataType::S32>(input1_shape, input1_data, _memory_manager.get());
+ Tensor input2_tensor =
+ makeInputTensor<DataType::S32>(input2_shape, input2_data, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::S32);
+
+ FloorMod kernel(&input1_tensor, &input2_tensor, &output_tensor);
+ kernel.configure();
+ _memory_manager->allocate_memory(output_tensor);
+ kernel.execute();
+
+ EXPECT_THAT(extractTensorData<int32_t>(output_tensor),
+ ::testing::ElementsAreArray(ref_output_data));
+ EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+}
+
+TEST_F(FloorModTest, NegativeValue)
+{
+ Shape input1_shape{1, 2, 2, 1};
+ std::vector<int32_t> input1_data{10, -9, -11, 7};
+
+ Shape input2_shape = input1_shape;
+ std::vector<int32_t> input2_data{2, 2, -3, -4};
+
+ std::vector<int32_t> ref_output_shape{1, 2, 2, 1};
+ std::vector<int32_t> ref_output_data{0, 1, -2, -1};
+
+ Tensor input1_tensor =
+ makeInputTensor<DataType::S32>(input1_shape, input1_data, _memory_manager.get());
+ Tensor input2_tensor =
+ makeInputTensor<DataType::S32>(input2_shape, input2_data, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::S32);
+
+ FloorMod kernel(&input1_tensor, &input2_tensor, &output_tensor);
+ kernel.configure();
+ _memory_manager->allocate_memory(output_tensor);
+ kernel.execute();
+
+ EXPECT_THAT(extractTensorData<int32_t>(output_tensor),
+ ::testing::ElementsAreArray(ref_output_data));
+ EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+}
+
+TEST_F(FloorModTest, BroadcastFloorMod)
+{
+ Shape input1_shape{1, 2, 2, 1};
+ std::vector<int32_t> input1_data{
+ 10,
+ -9,
+ -11,
+ 7,
+ };
+
+ Shape input2_shape{1};
+ std::vector<int32_t> input2_data{-3};
+
+ std::vector<int32_t> ref_output_shape{1, 2, 2, 1};
+ std::vector<int32_t> ref_output_data{-2, 0, -2, -2};
+
+ Tensor input1_tensor =
+ makeInputTensor<DataType::S32>(input1_shape, input1_data, _memory_manager.get());
+ Tensor input2_tensor =
+ makeInputTensor<DataType::S32>(input2_shape, input2_data, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::S32);
+
+ FloorMod kernel(&input1_tensor, &input2_tensor, &output_tensor);
+ kernel.configure();
+ _memory_manager->allocate_memory(output_tensor);
+ kernel.execute();
+
+ EXPECT_THAT(extractTensorData<int32_t>(output_tensor),
+ ::testing::ElementsAreArray(ref_output_data));
+ EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+}
+
+TEST_F(FloorModTest, Int64WithBroadcast)
+{
+ Shape input1_shape{1, 2, 2, 1};
+ std::vector<int64_t> input1_data{10, -9, -11, (1LL << 34) + 9};
+
+ Shape input2_shape{1};
+ std::vector<int64_t> input2_data{-(1LL << 33)};
+
+ std::vector<int32_t> ref_output_shape{1, 2, 2, 1};
+ std::vector<int64_t> ref_output_data{-8589934582, -9, -11, -8589934583};
+
+ Tensor input1_tensor =
+ makeInputTensor<DataType::S64>(input1_shape, input1_data, _memory_manager.get());
+ Tensor input2_tensor =
+ makeInputTensor<DataType::S64>(input2_shape, input2_data, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::S64);
+
+ FloorMod kernel(&input1_tensor, &input2_tensor, &output_tensor);
+ kernel.configure();
+ _memory_manager->allocate_memory(output_tensor);
+ kernel.execute();
+
+ EXPECT_THAT(extractTensorData<int64_t>(output_tensor),
+ ::testing::ElementsAreArray(ref_output_data));
+ EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+}
+
+TEST_F(FloorModTest, FloatSimple)
+{
+ Shape input1_shape{1, 2, 2, 1};
+ std::vector<float> input1_data{10.0, 9.0, 11.0, 3.0};
+
+ Shape input2_shape = input1_shape;
+ std::vector<float> input2_data{2.0, 2.0, 3.0, 4.0};
+
+ std::vector<int32_t> ref_output_shape{1, 2, 2, 1};
+ std::vector<float> ref_output_data{0.0, 1.0, 2.0, 3.0};
+
+ Tensor input1_tensor =
+ makeInputTensor<DataType::FLOAT32>(input1_shape, input1_data, _memory_manager.get());
+ Tensor input2_tensor =
+ makeInputTensor<DataType::FLOAT32>(input2_shape, input2_data, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+ FloorMod kernel(&input1_tensor, &input2_tensor, &output_tensor);
+ kernel.configure();
+ _memory_manager->allocate_memory(output_tensor);
+ kernel.execute();
+
+ EXPECT_THAT(extractTensorData<float>(output_tensor),
+ ::testing::ElementsAreArray(ref_output_data));
+ EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+}
+
+TEST_F(FloorModTest, FloatNegativeValue)
+{
+ Shape input1_shape{1, 2, 2, 1};
+ std::vector<float> input1_data{10.0, -9.0, -11.0, 7.0};
+
+ Shape input2_shape = input1_shape;
+ std::vector<float> input2_data{2.0, 2.0, -3.0, -4.0};
+
+ std::vector<int32_t> ref_output_shape{1, 2, 2, 1};
+ std::vector<float> ref_output_data{0.0, 1.0, -2.0, -1.0};
+
+ Tensor input1_tensor =
+ makeInputTensor<DataType::FLOAT32>(input1_shape, input1_data, _memory_manager.get());
+ Tensor input2_tensor =
+ makeInputTensor<DataType::FLOAT32>(input2_shape, input2_data, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+ FloorMod kernel(&input1_tensor, &input2_tensor, &output_tensor);
+ kernel.configure();
+ _memory_manager->allocate_memory(output_tensor);
+ kernel.execute();
+
+ EXPECT_THAT(extractTensorData<float>(output_tensor),
+ ::testing::ElementsAreArray(ref_output_data));
+ EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+}
+
+TEST_F(FloorModTest, FloatBroadcast)
+{
+ Shape input1_shape{1, 2, 2, 1};
+ std::vector<float> input1_data{
+ 10.0,
+ -9.0,
+ -11.0,
+ 7.0,
+ };
+
+ Shape input2_shape{1};
+ std::vector<float> input2_data{-3.0};
+
+ std::vector<int32_t> ref_output_shape{1, 2, 2, 1};
+ std::vector<float> ref_output_data{-2.0, 0.0, -2.0, -2.0};
+
+ Tensor input1_tensor =
+ makeInputTensor<DataType::FLOAT32>(input1_shape, input1_data, _memory_manager.get());
+ Tensor input2_tensor =
+ makeInputTensor<DataType::FLOAT32>(input2_shape, input2_data, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+ FloorMod kernel(&input1_tensor, &input2_tensor, &output_tensor);
+ kernel.configure();
+ _memory_manager->allocate_memory(output_tensor);
+ kernel.execute();
+
+ EXPECT_THAT(extractTensorData<float>(output_tensor),
+ ::testing::ElementsAreArray(ref_output_data));
+ EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+}
+
+TEST_F(FloorModTest, SimpleInt16)
+{
+ Shape input1_shape{1, 2, 2, 1};
+ std::vector<int16_t> input1_data{10, 9, 11, 3};
+
+ Shape input2_shape = input1_shape;
+ std::vector<int16_t> input2_data{2, 2, 3, 4};
+
+ std::vector<int32_t> ref_output_shape{1, 2, 2, 1};
+ std::vector<int16_t> ref_output_data{0, 1, 2, 3};
+
+ Tensor input1_tensor =
+ makeInputTensor<DataType::S16>(input1_shape, input1_data, _memory_manager.get());
+ Tensor input2_tensor =
+ makeInputTensor<DataType::S16>(input2_shape, input2_data, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::S16);
+
+ FloorMod kernel(&input1_tensor, &input2_tensor, &output_tensor);
+ kernel.configure();
+ _memory_manager->allocate_memory(output_tensor);
+ kernel.execute();
+
+ EXPECT_THAT(extractTensorData<int16_t>(output_tensor),
+ ::testing::ElementsAreArray(ref_output_data));
+ EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+}
+
+TEST_F(FloorModTest, NegativeValueInt16)
+{
+ Shape input1_shape{1, 2, 2, 1};
+ std::vector<int16_t> input1_data{110, -9, -11, 7};
+
+ Shape input2_shape = input1_shape;
+ std::vector<int16_t> input2_data{2, 2, -3, -4};
+
+ std::vector<int32_t> ref_output_shape{1, 2, 2, 1};
+ std::vector<int16_t> ref_output_data{0, 1, -2, -1};
+
+ Tensor input1_tensor =
+ makeInputTensor<DataType::S16>(input1_shape, input1_data, _memory_manager.get());
+ Tensor input2_tensor =
+ makeInputTensor<DataType::S16>(input2_shape, input2_data, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::S16);
+
+ FloorMod kernel(&input1_tensor, &input2_tensor, &output_tensor);
+ kernel.configure();
+ _memory_manager->allocate_memory(output_tensor);
+ kernel.execute();
+
+ EXPECT_THAT(extractTensorData<int16_t>(output_tensor),
+ ::testing::ElementsAreArray(ref_output_data));
+ EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+}
+
+TEST_F(FloorModTest, BroadcastFloorModInt16)
+{
+ Shape input1_shape{1, 2, 2, 1};
+ std::vector<int16_t> input1_data{10, -9, -11, 7};
+
+ Shape input2_shape{1};
+ std::vector<int16_t> input2_data{-3};
+
+ std::vector<int32_t> ref_output_shape{1, 2, 2, 1};
+ std::vector<int16_t> ref_output_data{-2, 0, -2, -2};
+
+ Tensor input1_tensor =
+ makeInputTensor<DataType::S16>(input1_shape, input1_data, _memory_manager.get());
+ Tensor input2_tensor =
+ makeInputTensor<DataType::S16>(input2_shape, input2_data, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::S16);
+
+ FloorMod kernel(&input1_tensor, &input2_tensor, &output_tensor);
+ kernel.configure();
+ _memory_manager->allocate_memory(output_tensor);
+ kernel.execute();
+
+ EXPECT_THAT(extractTensorData<int16_t>(output_tensor),
+ ::testing::ElementsAreArray(ref_output_data));
+ EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+}
+
+TEST_F(FloorModTest, DivByZero_NEG)
+{
+ Shape shape{3};
+ std::vector<int32_t> input1_data{1, 0, -1};
+ std::vector<int32_t> input2_data{0, 0, 0};
+
+ Tensor input1_tensor = makeInputTensor<DataType::S32>(shape, input1_data, _memory_manager.get());
+ Tensor input2_tensor = makeInputTensor<DataType::S32>(shape, input2_data, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::S32);
+
+ FloorMod kernel(&input1_tensor, &input2_tensor, &output_tensor);
+ kernel.configure();
+ _memory_manager->allocate_memory(output_tensor);
+
+ EXPECT_ANY_THROW(kernel.execute());
+}
+
+TEST_F(FloorModTest, Int64DivByZero_NEG)
+{
+ Shape shape{3};
+ std::vector<int64_t> input1_data{1, 0, -1};
+ std::vector<int64_t> input2_data{0, 0, 0};
+
+ Tensor input1_tensor = makeInputTensor<DataType::S64>(shape, input1_data, _memory_manager.get());
+ Tensor input2_tensor = makeInputTensor<DataType::S64>(shape, input2_data, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::S64);
+
+ FloorMod kernel(&input1_tensor, &input2_tensor, &output_tensor);
+ kernel.configure();
+ _memory_manager->allocate_memory(output_tensor);
+
+ EXPECT_ANY_THROW(kernel.execute());
+}
+
+TEST_F(FloorModTest, Int16DivByZero_NEG)
+{
+ Shape shape{3};
+ std::vector<int16_t> input1_data{1, 0, -1};
+ std::vector<int16_t> input2_data{0, 0, 0};
+
+ Tensor input1_tensor = makeInputTensor<DataType::S16>(shape, input1_data, _memory_manager.get());
+ Tensor input2_tensor = makeInputTensor<DataType::S16>(shape, input2_data, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::S16);
+
+ FloorMod kernel(&input1_tensor, &input2_tensor, &output_tensor);
+ kernel.configure();
+ _memory_manager->allocate_memory(output_tensor);
+
+ EXPECT_ANY_THROW(kernel.execute());
+}
+
+TEST_F(FloorModTest, Input_Output_Type_Mismatch_NEG)
+{
+ Tensor input1_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
+ Tensor input2_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::S8);
+
+ FloorMod kernel(&input1_tensor, &input2_tensor, &output_tensor);
+ EXPECT_ANY_THROW(kernel.configure());
+}
+
+TEST_F(FloorModTest, Input_Type_Mismatch_NEG)
+{
+ Tensor input1_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1}, _memory_manager.get());
+ Tensor input2_tensor = makeInputTensor<DataType::S8>({1}, {1}, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+ FloorMod kernel(&input1_tensor, &input2_tensor, &output_tensor);
+ EXPECT_ANY_THROW(kernel.configure());
+}
+
+TEST_F(FloorModTest, Float_Broadcast_NEG)
+{
+ Tensor input1_tensor = makeInputTensor<DataType::FLOAT32>({2}, {1.f, 2.f}, _memory_manager.get());
+ Tensor input2_tensor =
+ makeInputTensor<DataType::FLOAT32>({3}, {1.f, 2.f, 3.f}, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+ FloorMod kernel(&input1_tensor, &input2_tensor, &output_tensor);
+ ASSERT_ANY_THROW(kernel.configure());
+}
+
+TEST_F(FloorModTest, Int64_Broadcast_NEG)
+{
+ Tensor input1_tensor = makeInputTensor<DataType::S64>({2}, {1, 2}, _memory_manager.get());
+ Tensor input2_tensor = makeInputTensor<DataType::S64>({3}, {1, 2, 3}, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::S64);
+
+ FloorMod kernel(&input1_tensor, &input2_tensor, &output_tensor);
+ ASSERT_ANY_THROW(kernel.configure());
+}
+
+TEST_F(FloorModTest, Int32_Broadcast_NEG)
+{
+ Tensor input1_tensor = makeInputTensor<DataType::S32>({2}, {1, 2}, _memory_manager.get());
+ Tensor input2_tensor = makeInputTensor<DataType::S32>({3}, {1, 2, 3}, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::S32);
+
+ FloorMod kernel(&input1_tensor, &input2_tensor, &output_tensor);
+ ASSERT_ANY_THROW(kernel.configure());
+}
+
+TEST_F(FloorModTest, Int16_Broadcast_NEG)
+{
+ Tensor input1_tensor = makeInputTensor<DataType::S16>({2}, {1, 2}, _memory_manager.get());
+ Tensor input2_tensor = makeInputTensor<DataType::S16>({3}, {1, 2, 3}, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::S16);
+
+ FloorMod kernel(&input1_tensor, &input2_tensor, &output_tensor);
+ ASSERT_ANY_THROW(kernel.configure());
+}
+
+TEST_F(FloorModTest, UnsupportedType_NEG)
+{
+ Tensor input1_tensor = makeInputTensor<DataType::U8>({1}, {1}, _memory_manager.get());
+ Tensor input2_tensor = makeInputTensor<DataType::U8>({1}, {1}, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::U8);
+
+ FloorMod kernel(&input1_tensor, &input2_tensor, &output_tensor);
+ kernel.configure();
+
+ _memory_manager->allocate_memory(output_tensor);
+ ASSERT_ANY_THROW(kernel.execute());
+}
+
+} // namespace
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/Gelu.cpp b/compiler/luci-interpreter/src/kernels/Gelu.cpp
new file mode 100644
index 000000000..44e018e0e
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/Gelu.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/Gelu.h"
+
+#include "kernels/Utils.h"
+
+#include "PALGelu.h"
+
+#include <stdexcept>
+
+namespace luci_interpreter
+{
+
+namespace kernels
+{
+
+Gelu::Gelu(const Tensor *input, Tensor *output, const GeluParams &params)
+ : KernelWithParams<GeluParams>({input}, {output}, params)
+{
+}
+
+void Gelu::configure()
+{
+ LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
+
+ output()->resize(input()->shape());
+}
+
+void Gelu::execute() const
+{
+ switch (input()->element_type())
+ {
+ case DataType::FLOAT32:
+ evalFloat();
+ break;
+ default:
+ throw std::runtime_error("Unsupported type.");
+ }
+}
+
+void Gelu::evalFloat() const
+{
+ luci_interpreter_pal::Gelu(params().approximate, getTensorShape(input()),
+ getTensorData<float>(input()), getTensorShape(output()),
+ getTensorData<float>(output()));
+}
+
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Exp.h b/compiler/luci-interpreter/src/kernels/Gelu.h
index 51ba2cad1..c7c8bd971 100644
--- a/onert-micro/luci-interpreter/src/kernels/Exp.h
+++ b/compiler/luci-interpreter/src/kernels/Gelu.h
@@ -1,6 +1,5 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,8 +14,8 @@
* limitations under the License.
*/
-#ifndef LUCI_INTERPRETER_KERNELS_EXP_H
-#define LUCI_INTERPRETER_KERNELS_EXP_H
+#ifndef LUCI_INTERPRETER_KERNELS_GELU_H
+#define LUCI_INTERPRETER_KERNELS_GELU_H
#include "core/Kernel.h"
#include "core/KernelParams.h"
@@ -26,10 +25,10 @@ namespace luci_interpreter
namespace kernels
{
-class Exp : public Kernel
+class Gelu : public KernelWithParams<GeluParams>
{
public:
- Exp(const Tensor *input, Tensor *output);
+ Gelu(const Tensor *input, Tensor *output, const GeluParams &params);
const Tensor *input() const { return _inputs[0]; }
Tensor *output() const { return _outputs[0]; }
@@ -39,9 +38,12 @@ public:
private:
void evalFloat() const;
+
+private:
+ bool _approximate = false;
};
} // namespace kernels
} // namespace luci_interpreter
-#endif // LUCI_INTERPRETER_KERNELS_EXP_H
+#endif // LUCI_INTERPRETER_KERNELS_GELU_H
diff --git a/compiler/luci-interpreter/src/kernels/Gelu.test.cpp b/compiler/luci-interpreter/src/kernels/Gelu.test.cpp
new file mode 100644
index 000000000..64428098e
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/Gelu.test.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/Gelu.h"
+#include "kernels/TestUtils.h"
+#include "luci_interpreter/TestMemoryManager.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+namespace
+{
+
+using namespace testing;
+
+void Check(std::initializer_list<int32_t> input_shape, std::initializer_list<int32_t> output_shape,
+ std::initializer_list<float> input_data, std::initializer_list<float> output_data,
+ bool approximate)
+{
+ std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+ constexpr DataType element_type = getElementType<float>();
+ Tensor input_tensor =
+ makeInputTensor<element_type>(input_shape, input_data, memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(element_type);
+
+ GeluParams params{};
+ params.approximate = approximate;
+
+ Gelu kernel(&input_tensor, &output_tensor, params);
+
+ kernel.configure();
+ memory_manager->allocate_memory(output_tensor);
+ kernel.execute();
+
+ EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
+ EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(output_data));
+}
+
+class GeluTest : public ::testing::Test
+{
+};
+
+TEST_F(GeluTest, Simple)
+{
+ Check(/*input_shape=*/{2, 3}, /*output_shape=*/{2, 3},
+ /*input_data=*/
+ {
+ 0.0f, 1.0f, 3.0f, // Row 1
+ 1.0f, -1.0f, -2.0f, // Row 2
+ },
+ /*output_data=*/
+ {
+ 0.0f, 0.841345f, 2.99595f, // Row 1
+ 0.841345f, -0.158655f, -0.0455003f, // Row 2
+ },
+ /*approximate=*/false);
+
+ SUCCEED();
+}
+
+TEST_F(GeluTest, Approximate)
+{
+ Check(/*input_shape=*/{2, 3}, /*output_shape=*/{2, 3},
+ /*input_data=*/
+ {
+ 0.0f, 1.0f, 3.0f, // Row 1
+ 1.0f, -1.0f, -2.0f, // Row 2
+ },
+ /*output_data=*/
+ {
+ 0.0f, 0.841192f, 2.99636f, // Row 1
+ 0.841192f, -0.158808f, -0.0454023f, // Row 2
+ },
+ /*approximate=*/true);
+
+ SUCCEED();
+}
+
+TEST_F(GeluTest, DifferentInOutType_NEG)
+{
+ std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+ Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({2, 3},
+ {
+ 0.0f, 1.0f, 3.0f, // Row 1
+ 1.0f, -1.0f, -2.0f, // Row 2
+ },
+ memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::U8);
+
+ GeluParams params{};
+ params.approximate = false;
+
+ Gelu kernel(&input_tensor, &output_tensor, params);
+
+ EXPECT_ANY_THROW(kernel.configure());
+}
+
+} // namespace
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/HardSwish.cpp b/compiler/luci-interpreter/src/kernels/HardSwish.cpp
new file mode 100644
index 000000000..b1008459a
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/HardSwish.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/HardSwish.h"
+#include "kernels/Utils.h"
+
+#include "PALHardSwish.h"
+
+#include <stdexcept>
+
+namespace luci_interpreter
+{
+
+namespace kernels
+{
+
+HardSwish::HardSwish(const Tensor *input, Tensor *output) : Kernel({input}, {output}) {}
+
+void HardSwish::configure()
+{
+ LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
+ output()->resize(input()->shape());
+}
+
+void HardSwish::execute() const
+{
+ switch (input()->element_type())
+ {
+ case DataType::FLOAT32:
+ luci_interpreter_pal::HardSwish(getTensorShape(input()), getTensorData<float>(input()),
+ getTensorShape(output()), getTensorData<float>(output()));
+ break;
+ default:
+ throw std::runtime_error("Unsupported type.");
+ }
+}
+
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Elu.h b/compiler/luci-interpreter/src/kernels/HardSwish.h
index 67a922b07..bb9e9b653 100644
--- a/onert-micro/luci-interpreter/src/kernels/Elu.h
+++ b/compiler/luci-interpreter/src/kernels/HardSwish.h
@@ -1,6 +1,5 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,8 +14,8 @@
* limitations under the License.
*/
-#ifndef LUCI_INTERPRETER_KERNELS_ELU_H
-#define LUCI_INTERPRETER_KERNELS_ELU_H
+#ifndef LUCI_INTERPRETER_KERNELS_HARDSWISH_H
+#define LUCI_INTERPRETER_KERNELS_HARDSWISH_H
#include "core/Kernel.h"
#include "core/KernelParams.h"
@@ -26,10 +25,10 @@ namespace luci_interpreter
namespace kernels
{
-class Elu : public Kernel
+class HardSwish : public Kernel
{
public:
- Elu(const Tensor *input, Tensor *output);
+ HardSwish(const Tensor *input, Tensor *output);
const Tensor *input() const { return _inputs[0]; }
Tensor *output() const { return _outputs[0]; }
@@ -41,4 +40,4 @@ public:
} // namespace kernels
} // namespace luci_interpreter
-#endif // LUCI_INTERPRETER_KERNELS_ELU_H
+#endif // LUCI_INTERPRETER_KERNELS_HARDSWISH_H
diff --git a/compiler/luci-interpreter/src/kernels/HardSwish.test.cpp b/compiler/luci-interpreter/src/kernels/HardSwish.test.cpp
new file mode 100644
index 000000000..c055fee0e
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/HardSwish.test.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/HardSwish.h"
+#include "kernels/TestUtils.h"
+#include "luci_interpreter/TestMemoryManager.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+namespace
+{
+
+using namespace testing;
+
+void Check(std::initializer_list<int32_t> input_shape, std::initializer_list<int32_t> output_shape,
+ std::initializer_list<float> input_data, std::initializer_list<float> output_data)
+{
+ std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+ Tensor input_tensor =
+ makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+ HardSwish kernel(&input_tensor, &output_tensor);
+ kernel.configure();
+ memory_manager->allocate_memory(output_tensor);
+ kernel.execute();
+
+ (void)output_shape;
+ EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(output_data));
+}
+
+TEST(HardSwishTest, SimpleHardSwish)
+{
+ Check(
+ /*input_shape=*/{1, 2, 4, 1}, /*output_shape=*/{1, 2, 4, 1},
+ /*input_data=*/
+ {
+ 0, -6, 2, -4, //
+ 3, -2, 10, -0.1, //
+ },
+ /*output_data=*/
+ {
+ 0, -0, 1.66667, -0, //
+ 3, -0.333333, 10, -0.0483333, //
+ });
+}
+
+TEST(HardSwishTest, InOutTypeMismatch_NEG)
+{
+ std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+ Shape input_shape{1, 2, 4, 1};
+ std::vector<float> input_data{
+ 0, -6, 2, -4, //
+ 3, -2, 10, -0.1, //
+ };
+ Tensor input_tensor =
+ makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::U8);
+
+ HardSwish kernel(&input_tensor, &output_tensor);
+ EXPECT_ANY_THROW(kernel.configure());
+}
+
+} // namespace
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/Log.cpp b/compiler/luci-interpreter/src/kernels/Log.cpp
new file mode 100644
index 000000000..fa5f90e66
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/Log.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/Log.h"
+#include "kernels/Utils.h"
+
+#include <cmath>
+
+namespace luci_interpreter
+{
+
+namespace kernels
+{
+
+Log::Log(const Tensor *input, Tensor *output) : Kernel({input}, {output}) {}
+
+void Log::configure() { output()->resize(input()->shape()); }
+
+void Log::execute() const
+{
+ switch (input()->element_type())
+ {
+ case DataType::FLOAT32:
+ evalFloat();
+ break;
+ default:
+ throw std::runtime_error("Unsupported type.");
+ }
+}
+
+void Log::evalFloat() const
+{
+ const auto input_data = getTensorData<float>(input());
+ const auto input_shape = input()->shape();
+ auto output_data = getTensorData<float>(output());
+ for (int64_t i = 0; i < input_shape.num_elements(); ++i)
+ {
+ output_data[i] = std::log(input_data[i]);
+ }
+}
+
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Relu6.h b/compiler/luci-interpreter/src/kernels/Log.h
index 61aba6773..49b293764 100644
--- a/onert-micro/luci-interpreter/src/kernels/Relu6.h
+++ b/compiler/luci-interpreter/src/kernels/Log.h
@@ -1,6 +1,5 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,8 +14,8 @@
* limitations under the License.
*/
-#ifndef LUCI_INTERPRETER_KERNELS_RELU6_H
-#define LUCI_INTERPRETER_KERNELS_RELU6_H
+#ifndef LUCI_INTERPRETER_KERNELS_LOG_H
+#define LUCI_INTERPRETER_KERNELS_LOG_H
#include "core/Kernel.h"
@@ -25,10 +24,10 @@ namespace luci_interpreter
namespace kernels
{
-class Relu6 : public Kernel
+class Log : public Kernel
{
public:
- Relu6(const Tensor *input, Tensor *output);
+ Log(const Tensor *input, Tensor *output);
const Tensor *input() const { return _inputs[0]; }
Tensor *output() const { return _outputs[0]; }
@@ -38,7 +37,6 @@ public:
private:
void evalFloat() const;
- void evalQuantized() const;
private:
int32_t _output_multiplier{0};
@@ -48,4 +46,4 @@ private:
} // namespace kernels
} // namespace luci_interpreter
-#endif // LUCI_INTERPRETER_KERNELS_RELU6_H
+#endif // LUCI_INTERPRETER_KERNELS_LOG_H
diff --git a/compiler/luci-interpreter/src/kernels/Log.test.cpp b/compiler/luci-interpreter/src/kernels/Log.test.cpp
new file mode 100644
index 000000000..3e360e098
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/Log.test.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2018 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/Log.h"
+#include "kernels/TestUtils.h"
+#include "luci_interpreter/TestMemoryManager.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+namespace
+{
+
+using namespace testing;
+
+class LogTest : public ::testing::Test
+{
+protected:
+ void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
+
+ std::unique_ptr<IMemoryManager> _memory_manager;
+};
+
+TEST_F(LogTest, FloatSimple)
+{
+ std::vector<float> input_data{1, 3.1415926, 1, 1};
+
+ std::vector<float> ref_output_data{0, 1.14473, 0, 0};
+
+ Tensor input_tensor =
+ makeInputTensor<DataType::FLOAT32>({1, 1, 4, 1}, input_data, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+ Log kernel(&input_tensor, &output_tensor);
+ kernel.configure();
+ _memory_manager->allocate_memory(output_tensor);
+ kernel.execute();
+
+ EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
+ EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 1, 4, 1}));
+}
+
+TEST_F(LogTest, Invalid_Input_Type_NEG)
+{
+ Tensor input_tensor = makeInputTensor<DataType::S64>({1}, {1}, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::S64);
+
+ Log kernel(&input_tensor, &output_tensor);
+ kernel.configure();
+ _memory_manager->allocate_memory(output_tensor);
+ EXPECT_ANY_THROW(kernel.execute());
+}
+
+} // namespace
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/Reshape.cpp b/compiler/luci-interpreter/src/kernels/Reshape.cpp
index 61d3300b2..d3234e483 100644
--- a/compiler/luci-interpreter/src/kernels/Reshape.cpp
+++ b/compiler/luci-interpreter/src/kernels/Reshape.cpp
@@ -17,6 +17,8 @@
#include "kernels/Reshape.h"
+#include "kernels/Utils.h"
+
#include <cassert>
#include <cstring>
@@ -28,12 +30,26 @@ namespace kernels
static Shape extractShapeFromTensor(const Tensor *tensor)
{
- assert(tensor->element_type() == DataType::S32);
Shape shape(tensor->shape().num_elements());
- const auto *shape_data = tensor->data<int32_t>();
- for (int i = 0; i < tensor->shape().num_elements(); ++i)
+ if (tensor->element_type() == DataType::S32)
+ {
+ const auto *shape_data = tensor->data<int32_t>();
+ for (int i = 0; i < tensor->shape().num_elements(); ++i)
+ {
+ shape.dim(i) = shape_data[i];
+ }
+ }
+ else if (tensor->element_type() == DataType::S64)
+ {
+ const auto *shape_data = tensor->data<int64_t>();
+ for (int i = 0; i < tensor->shape().num_elements(); ++i)
+ {
+ shape.dim(i) = static_cast<int32_t>(shape_data[i]);
+ }
+ }
+ else
{
- shape.dim(i) = shape_data[i];
+ LUCI_INTERPRETER_CHECK(false);
}
return shape;
}
diff --git a/compiler/luci-interpreter/src/kernels/Reshape.test.cpp b/compiler/luci-interpreter/src/kernels/Reshape.test.cpp
index c2ff3ea1b..7c0522ebe 100644
--- a/compiler/luci-interpreter/src/kernels/Reshape.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Reshape.test.cpp
@@ -77,6 +77,42 @@ TEST_F(ReshapeTest, UnknownDimension)
EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(input_data));
}
+TEST_F(ReshapeTest, SupportS64)
+{
+ Shape input_shape{2, 1, 2, 3};
+ std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
+ Shape shape_shape{3};
+ std::vector<int64_t> shape_data{2, -1, 2};
+ Tensor input_tensor =
+ makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
+ Tensor shape_tensor =
+ makeInputTensor<DataType::S64>(shape_shape, shape_data, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+ Reshape kernel(&input_tensor, &shape_tensor, &output_tensor);
+ kernel.configure();
+ _memory_manager->allocate_memory(output_tensor);
+ kernel.execute();
+
+ EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(input_data));
+}
+
+TEST_F(ReshapeTest, SupportS16_NEG)
+{
+ Shape input_shape{2, 1, 2, 3};
+ std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
+ Shape shape_shape{3};
+ std::vector<int16_t> shape_data{2, -1, 2};
+ Tensor input_tensor =
+ makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
+ Tensor shape_tensor =
+ makeInputTensor<DataType::S16>(shape_shape, shape_data, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+ Reshape kernel(&input_tensor, &shape_tensor, &output_tensor);
+ EXPECT_ANY_THROW(kernel.configure());
+}
+
} // namespace
} // namespace kernels
} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/Select.cpp b/compiler/luci-interpreter/src/kernels/Select.cpp
new file mode 100644
index 000000000..b4ab5f621
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/Select.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2018 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/Select.h"
+#include "kernels/Utils.h"
+
+#include <tensorflow/lite/kernels/internal/reference/reference_ops.h>
+// TODO use select.h when version up
+// #include <tensorflow/lite/kernels/internal/reference/select.h>
+
+#include <stdexcept>
+
+namespace luci_interpreter
+{
+
+namespace kernels
+{
+
+Select::Select(const Tensor *condition, const Tensor *t, const Tensor *e, Tensor *output)
+ : Kernel({condition, t, e}, {output})
+{
+ // NOTE _requires_broadcast is for SelectV2
+ _requires_broadcast = false;
+ _has_low_rank_input_condition = false;
+}
+
+void Select::configure()
+{
+ LUCI_INTERPRETER_CHECK(condition()->element_type() == DataType::BOOL);
+ LUCI_INTERPRETER_CHECK(t()->element_type() == e()->element_type());
+ LUCI_INTERPRETER_CHECK(t()->element_type() == output()->element_type());
+
+ auto cond_shape = condition()->shape();
+ auto cond_num_dims = cond_shape.num_dims();
+ auto t_shape = t()->shape();
+
+ bool is_input_condition_scalar = cond_num_dims == 0;
+ bool has_rank_one_input_condition = cond_num_dims == 1 && cond_shape.dim(0) == t_shape.dim(0);
+
+ _has_low_rank_input_condition = is_input_condition_scalar || has_rank_one_input_condition;
+
+ output()->resize(calculateShapeForBroadcast(t()->shape(), e()->shape()));
+}
+
+void Select::execute() const
+{
+ switch (t()->element_type())
+ {
+ case DataType::FLOAT32:
+ evalFloat();
+ break;
+ default:
+ throw std::runtime_error("Select: unsupported type.");
+ }
+}
+
+void Select::evalFloat() const
+{
+ const auto condition_shape = getTensorShape(condition());
+ const auto condition_data = getTensorData<bool>(condition());
+ const auto t_shape = getTensorShape(t());
+ const auto t_data = getTensorData<float>(t());
+ const auto e_shape = getTensorShape(e());
+ const auto e_data = getTensorData<float>(e());
+ const auto output_shape = getTensorShape(output());
+ auto output_data = getTensorData<float>(output());
+
+ if (_has_low_rank_input_condition)
+ {
+ tflite::reference_ops::RankOneSelect(condition_shape, condition_data, t_shape, t_data, e_shape,
+ e_data, output_shape, output_data);
+ }
+ else if (_requires_broadcast)
+ {
+ // TODO support broadcast kernel when upgrade to TF2.10.x or above
+ assert(false);
+ }
+ else
+ {
+ tflite::reference_ops::Select(condition_shape, condition_data, t_shape, t_data, e_shape, e_data,
+ output_shape, output_data);
+ }
+}
+
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Greater.h b/compiler/luci-interpreter/src/kernels/Select.h
index 8e4369f6c..d67b4f5fc 100644
--- a/onert-micro/luci-interpreter/src/kernels/Greater.h
+++ b/compiler/luci-interpreter/src/kernels/Select.h
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2018 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,8 +15,8 @@
* limitations under the License.
*/
-#ifndef LUCI_INTERPRETER_KERNELS_GREATER_H
-#define LUCI_INTERPRETER_KERNELS_GREATER_H
+#ifndef LUCI_INTERPRETER_KERNELS_SELECT_H
+#define LUCI_INTERPRETER_KERNELS_SELECT_H
#include "core/Kernel.h"
@@ -25,13 +25,14 @@ namespace luci_interpreter
namespace kernels
{
-class Greater : public Kernel
+class Select : public Kernel
{
public:
- Greater(const Tensor *x, const Tensor *y, Tensor *output);
+ Select(const Tensor *cond, const Tensor *t, const Tensor *e, Tensor *output);
- const Tensor *x() const { return _inputs[0]; }
- const Tensor *y() const { return _inputs[1]; }
+ const Tensor *condition() const { return _inputs[0]; }
+ const Tensor *t() const { return _inputs[1]; }
+ const Tensor *e() const { return _inputs[2]; }
Tensor *output() const { return _outputs[0]; }
void configure() override;
@@ -39,17 +40,16 @@ public:
private:
void evalFloat() const;
- template <typename T> void evalInteger() const;
- void evalQuantized() const;
private:
- int32_t _x_multiplier = 0;
- int _x_shift = 0;
- int32_t _y_multiplier = 0;
- int _y_shift = 0;
+ // for SelectV2
+ bool _requires_broadcast = false;
+ // True if input condition is scalar or input condition has rank one and
+ // matches the first dimension of other inputs.
+ bool _has_low_rank_input_condition = false;
};
} // namespace kernels
} // namespace luci_interpreter
-#endif // LUCI_INTERPRETER_KERNELS_GREATER_H
+#endif // LUCI_INTERPRETER_KERNELS_SELECT_H
diff --git a/compiler/luci-interpreter/src/kernels/Select.test.cpp b/compiler/luci-interpreter/src/kernels/Select.test.cpp
new file mode 100644
index 000000000..f74d18dc4
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/Select.test.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2018 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/Select.h"
+#include "kernels/TestUtils.h"
+
+#include "luci_interpreter/TestMemoryManager.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+namespace
+{
+
+using namespace testing;
+
+class SelectTest : public ::testing::Test
+{
+protected:
+ void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
+
+ std::unique_ptr<IMemoryManager> _memory_manager;
+};
+
+std::vector<unsigned char> c_data{
+ 1, 1, 1, // Row 1
+ 0, 0, 0, // Row 2
+};
+
+std::vector<float> t_data{
+ 0.5, 0.7, 0.9, // Row 1
+ 1, 0, -1, // Row 2
+};
+
+std::vector<float> e_data{
+ 0.9, 0.7, 0.5, // Row 1
+ -1, 0, 1, // Row 2
+};
+
+std::vector<float> ref_output_data{
+ 0.5, 0.7, 0.9, // Row 1
+ -1, 0, 1, // Row 2
+};
+
+TEST_F(SelectTest, FloatSimple)
+{
+ Tensor c_tensor = makeInputTensor<DataType::BOOL>({2, 3}, c_data, _memory_manager.get());
+ Tensor t_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, t_data, _memory_manager.get());
+ Tensor e_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, e_data, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+ Select kernel(&c_tensor, &t_tensor, &e_tensor, &output_tensor);
+ kernel.configure();
+ _memory_manager->allocate_memory(output_tensor);
+ kernel.execute();
+
+ EXPECT_THAT(extractTensorData<float>(output_tensor),
+ ::testing::ElementsAreArray(ref_output_data));
+ EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({2, 3}));
+}
+
+TEST_F(SelectTest, Invalid_C_Type_NEG)
+{
+ std::vector<float> i_c_data{
+ 1, 1, 1, // Row 1
+ 0, 0, 0, // Row 2
+ };
+
+ Tensor c_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, i_c_data, _memory_manager.get());
+ Tensor t_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, t_data, _memory_manager.get());
+ Tensor e_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, e_data, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+ Select kernel(&c_tensor, &t_tensor, &e_tensor, &output_tensor);
+ EXPECT_ANY_THROW(kernel.configure());
+}
+
+TEST_F(SelectTest, Invalid_O_Type_NEG)
+{
+ Tensor c_tensor = makeInputTensor<DataType::BOOL>({2, 3}, c_data, _memory_manager.get());
+ Tensor t_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, t_data, _memory_manager.get());
+ Tensor e_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, e_data, _memory_manager.get());
+ Tensor output_tensor = makeOutputTensor(DataType::BOOL);
+
+ Select kernel(&c_tensor, &t_tensor, &e_tensor, &output_tensor);
+ EXPECT_ANY_THROW(kernel.configure());
+}
+
+} // namespace
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/Sub.cpp b/compiler/luci-interpreter/src/kernels/Sub.cpp
index 24b6a72e5..1fd583c62 100644
--- a/compiler/luci-interpreter/src/kernels/Sub.cpp
+++ b/compiler/luci-interpreter/src/kernels/Sub.cpp
@@ -148,7 +148,7 @@ void Sub::evalQuantized() const
if (need_broadcast)
{
- tflite::reference_ops::BroadcastSubSlow(
+ tflite::reference_ops::BroadcastQuantSubSlow(
params, getTensorShape(input1()), getTensorData<uint8_t>(input1()), getTensorShape(input2()),
getTensorData<uint8_t>(input2()), getTensorShape(output()), getTensorData<uint8_t>(output()));
}
diff --git a/compiler/luci-interpreter/src/kernels/Sum.cpp b/compiler/luci-interpreter/src/kernels/Sum.cpp
new file mode 100644
index 000000000..645f02c36
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/Sum.cpp
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/Sum.h"
+
+#include "kernels/Utils.h"
+
+#include <tensorflow/lite/kernels/internal/reference/reduce.h>
+
+#include <stdexcept>
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+// Returns the number of axes that will be reduced. Removes duplicates.
+static int getAxisReductionCount(const int32_t *axes_data, int num_axes, int input_num_dims)
+{
+ int reduction_count = num_axes;
+ for (int i = 0; i < num_axes; ++i)
+ {
+ int current = axes_data[i] >= 0 ? axes_data[i] : axes_data[i] + input_num_dims;
+ assert(current >= 0 && current < input_num_dims);
+ for (int j = 0; j < i; j++)
+ {
+ int previous = axes_data[j] >= 0 ? axes_data[j] : axes_data[j] + input_num_dims;
+ // This checks for duplicate axis
+ if (current == previous)
+ {
+ --reduction_count;
+ break;
+ }
+ }
+ }
+ return reduction_count;
+}
+
+static Shape getOutputShape(const Shape &input_shape, const int32_t *axes_data, int num_axes,
+ bool keep_dims)
+{
+ int input_num_dims = input_shape.num_dims();
+ if (input_num_dims == 0)
+ {
+ return Shape(0);
+ }
+
+ if (keep_dims)
+ {
+ Shape output_shape(input_num_dims);
+ for (int idx = 0; idx < input_num_dims; ++idx)
+ {
+ bool is_axis = false;
+ for (int axis_idx = 0; axis_idx < num_axes; ++axis_idx)
+ {
+ if (axes_data[axis_idx] == idx || axes_data[axis_idx] + input_num_dims == idx)
+ {
+ is_axis = true;
+ break;
+ }
+ }
+ if (is_axis)
+ {
+ output_shape.dim(idx) = 1;
+ }
+ else
+ {
+ output_shape.dim(idx) = input_shape.dim(idx);
+ }
+ }
+ return output_shape;
+ }
+ else
+ {
+ int num_reduce_axes = getAxisReductionCount(axes_data, num_axes, input_num_dims);
+ Shape output_shape(input_num_dims - num_reduce_axes);
+ int num_skip_axes = 0;
+ for (int idx = 0; idx < input_num_dims; ++idx)
+ {
+ bool is_axis = false;
+ for (int axis_idx = 0; axis_idx < num_axes; ++axis_idx)
+ {
+ if (axes_data[axis_idx] == idx || axes_data[axis_idx] + input_num_dims == idx)
+ {
+ ++num_skip_axes;
+ is_axis = true;
+ break;
+ }
+ }
+ if (!is_axis)
+ {
+ output_shape.dim(idx - num_skip_axes) = input_shape.dim(idx);
+ }
+ }
+ return output_shape;
+ }
+}
+
+Sum::Sum(const Tensor *input, const Tensor *axes, Tensor *output, Tensor *temp_index,
+ Tensor *resolved_axes, const ReducerParams &params)
+ : KernelWithParams<ReducerParams>({input, axes}, {output, temp_index, resolved_axes}, params)
+{
+}
+
+void Sum::configure()
+{
+ LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
+ LUCI_INTERPRETER_CHECK(axes()->element_type() == DataType::S32);
+
+ const Shape &input_shape = input()->shape();
+ int input_num_dims = input_shape.num_dims();
+
+ const auto *axes_data = getTensorData<int32_t>(axes());
+ int num_axes = axes()->shape().num_elements();
+ LUCI_INTERPRETER_CHECK(num_axes <= 4);
+
+ // We compute shapes of outputs in configure, assuming that outputs have
+ // static shape
+ // TODO Support dynamic shape
+ Shape output_shape = getOutputShape(input_shape, axes_data, num_axes, _params.keep_dims);
+ output()->resize(output_shape);
+
+ auto temp_index = getOutputTensors()[1];
+ auto resolved_axes = getOutputTensors()[2];
+
+ temp_index->resize(Shape(input_num_dims));
+ resolved_axes->resize(Shape(num_axes));
+}
+
+void Sum::execute() const
+{
+ switch (input()->element_type())
+ {
+ case DataType::FLOAT32:
+ evalFloat();
+ break;
+ default:
+ throw std::runtime_error("Unsupported type.");
+ }
+}
+
+void Sum::evalFloat() const
+{
+ const auto *axes_data = getTensorData<int32_t>(axes());
+ int num_axes = axes()->shape().num_elements();
+
+ auto temp_index = getOutputTensors()[1];
+ auto resolved_axes = getOutputTensors()[2];
+
+ int num_resolved_axis = 0;
+ LUCI_INTERPRETER_CHECK(
+ tflite::reference_ops::ResolveAxis(input()->shape().num_dims(), axes_data, num_axes,
+ getTensorData<int>(resolved_axes), &num_resolved_axis));
+
+ float init_value = 0.0;
+ tflite::reference_ops::ReduceGeneric<float>(
+ getTensorData<float>(input()), getTensorShape(input()).DimsData(), input()->shape().num_dims(),
+ getTensorData<float>(output()), getTensorShape(output()).DimsData(),
+ output()->shape().num_dims(), axes_data, num_axes, _params.keep_dims,
+ getTensorData<int>(temp_index), getTensorData<int>(resolved_axes), init_value,
+ [](const float current, const float in) -> float { return current + in; });
+}
+
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Shape.h b/compiler/luci-interpreter/src/kernels/Sum.h
index dcf526dab..290e0dafa 100644
--- a/onert-micro/luci-interpreter/src/kernels/Shape.h
+++ b/compiler/luci-interpreter/src/kernels/Sum.h
@@ -1,6 +1,5 @@
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,33 +14,38 @@
* limitations under the License.
*/
-#ifndef LUCI_INTERPRETER_KERNELS_SHAPE_H
-#define LUCI_INTERPRETER_KERNELS_SHAPE_H
+#ifndef LUCI_INTERPRETER_KERNELS_SUM_H
+#define LUCI_INTERPRETER_KERNELS_SUM_H
#include "core/Kernel.h"
#include "core/KernelParams.h"
+#include <memory>
+
namespace luci_interpreter
{
namespace kernels
{
-class ShapeKernel : public KernelWithParams<ShapeParams>
+class Sum : public KernelWithParams<ReducerParams>
{
public:
- ShapeKernel(const Tensor *input, Tensor *output, const ShapeParams &params);
+ // TODO Add temp_sum to support quantized kernels
+ Sum(const Tensor *input, const Tensor *axes, Tensor *output, Tensor *temp_index,
+ Tensor *resolved_axes, const ReducerParams &params);
const Tensor *input() const { return _inputs[0]; }
+ const Tensor *axes() const { return _inputs[1]; }
Tensor *output() const { return _outputs[0]; }
void configure() override;
void execute() const override;
private:
- template <typename T> void evalInt() const;
+ void evalFloat() const;
};
} // namespace kernels
} // namespace luci_interpreter
-#endif // LUCI_INTERPRETER_KERNELS_SHAPE_H
+#endif // LUCI_INTERPRETER_KERNELS_SUM_H
diff --git a/compiler/luci-interpreter/src/kernels/Sum.test.cpp b/compiler/luci-interpreter/src/kernels/Sum.test.cpp
new file mode 100644
index 000000000..e2dc3012b
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/Sum.test.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/Sum.h"
+#include "kernels/TestUtils.h"
+#include "luci_interpreter/TestMemoryManager.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+namespace
+{
+
+using namespace testing;
+
+class SumTest : public ::testing::Test
+{
+protected:
+ void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
+
+ std::unique_ptr<IMemoryManager> _memory_manager;
+};
+
+TEST_F(SumTest, FloatNotKeepDims)
+{
+ std::vector<float> input_data = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0,
+ 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0,
+ 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0};
+
+ std::vector<int32_t> axis_data{1, 0};
+ Tensor input_tensor =
+ makeInputTensor<DataType::FLOAT32>({4, 3, 2}, input_data, _memory_manager.get());
+ Tensor axis_tensor = makeInputTensor<DataType::S32>({2}, axis_data, _memory_manager.get());
+ Tensor temp_index(DataType::S32, Shape({}), {}, "");
+ Tensor resolved_axes(DataType::S32, Shape({}), {}, "");
+ Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+ ReducerParams params{};
+ params.keep_dims = false;
+
+ Sum kernel(&input_tensor, &axis_tensor, &output_tensor, &temp_index, &resolved_axes, params);
+ kernel.configure();
+ _memory_manager->allocate_memory(temp_index);
+ _memory_manager->allocate_memory(resolved_axes);
+ _memory_manager->allocate_memory(output_tensor);
+ kernel.execute();
+
+ std::vector<float> ref_output_data{144, 156};
+ std::initializer_list<int32_t> ref_output_shape{2};
+ EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
+ EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+}
+
+TEST_F(SumTest, FloatKeepDims)
+{
+ std::vector<float> input_data = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0,
+ 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0,
+ 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0};
+
+ std::vector<int32_t> axis_data{0, 2};
+ Tensor input_tensor =
+ makeInputTensor<DataType::FLOAT32>({4, 3, 2}, input_data, _memory_manager.get());
+ Tensor axis_tensor = makeInputTensor<DataType::S32>({2}, axis_data, _memory_manager.get());
+ Tensor temp_index(DataType::S32, Shape({}), {}, "");
+ Tensor resolved_axes(DataType::S32, Shape({}), {}, "");
+ Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+ ReducerParams params{};
+ params.keep_dims = true;
+
+ Sum kernel(&input_tensor, &axis_tensor, &output_tensor, &temp_index, &resolved_axes, params);
+ kernel.configure();
+ _memory_manager->allocate_memory(temp_index);
+ _memory_manager->allocate_memory(resolved_axes);
+ _memory_manager->allocate_memory(output_tensor);
+ kernel.execute();
+
+ std::vector<float> ref_output_data{84, 100, 116};
+ std::initializer_list<int32_t> ref_output_shape{1, 3, 1};
+ EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
+ EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+}
+
+TEST_F(SumTest, Input_Output_Type_NEG)
+{
+ std::vector<float> input_data = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0,
+ 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0,
+ 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0};
+
+ std::vector<int32_t> axis_data{0, 2};
+ Tensor input_tensor =
+ makeInputTensor<DataType::FLOAT32>({4, 3, 2}, input_data, _memory_manager.get());
+ Tensor axis_tensor = makeInputTensor<DataType::S32>({2}, axis_data, _memory_manager.get());
+ Tensor temp_index(DataType::S32, Shape({}), {}, "");
+ Tensor resolved_axes(DataType::S32, Shape({}), {}, "");
+ Tensor output_tensor = makeOutputTensor(DataType::U8);
+
+ ReducerParams params{};
+ params.keep_dims = true;
+
+ Sum kernel(&input_tensor, &axis_tensor, &output_tensor, &temp_index, &resolved_axes, params);
+
+ EXPECT_ANY_THROW(kernel.configure());
+}
+
+TEST_F(SumTest, Invalid_Axes_Type_NEG)
+{
+ std::vector<float> input_data = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0,
+ 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0,
+ 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0};
+
+ std::vector<int64_t> axis_data{0, 2};
+ Tensor input_tensor =
+ makeInputTensor<DataType::FLOAT32>({4, 3, 2}, input_data, _memory_manager.get());
+ Tensor axis_tensor = makeInputTensor<DataType::S64>({2}, axis_data, _memory_manager.get());
+ Tensor temp_index(DataType::S32, Shape({}), {}, "");
+ Tensor resolved_axes(DataType::S32, Shape({}), {}, "");
+ Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+ ReducerParams params{};
+ params.keep_dims = true;
+
+ Sum kernel(&input_tensor, &axis_tensor, &output_tensor, &temp_index, &resolved_axes, params);
+
+ EXPECT_ANY_THROW(kernel.configure());
+}
+
+} // namespace
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/TransposeConv.test.cpp b/compiler/luci-interpreter/src/kernels/TransposeConv.test.cpp
index 4856e1b87..8e9cfc6ad 100644
--- a/compiler/luci-interpreter/src/kernels/TransposeConv.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/TransposeConv.test.cpp
@@ -54,6 +54,7 @@ void Check(std::initializer_list<int32_t> output_shape_shape,
params.padding = padding;
params.stride_height = stride_height;
params.stride_width = stride_width;
+ params.activation = luci::FusedActFunc::NONE;
if (bias_data.size() != 0)
{
@@ -164,6 +165,7 @@ TEST(TransposeConvTest, UInt8)
params.padding = Padding::VALID;
params.stride_height = 2;
params.stride_width = 2;
+ params.activation = luci::FusedActFunc::NONE;
TransposeConv kernel(&output_shape_tensor, &filter_tensor, &input_tensor, &bias_tensor,
&output_tensor, &scratch_tensor, params);
@@ -232,6 +234,7 @@ TEST(TransposeConvTest, UInt8_CWQ)
params.padding = Padding::VALID;
params.stride_height = 2;
params.stride_width = 2;
+ params.activation = luci::FusedActFunc::NONE;
TransposeConv kernel(&output_shape_tensor, &filter_tensor, &input_tensor, &bias_tensor,
&output_tensor, &scratch_tensor, params);
@@ -278,6 +281,7 @@ TEST(TransposeConvTest, SInt16)
params.padding = Padding::VALID;
params.stride_height = 2;
params.stride_width = 2;
+ params.activation = luci::FusedActFunc::NONE;
TransposeConv kernel(&output_shape_tensor, &filter_tensor, &input_tensor, &bias_tensor,
&output_tensor, &scratch_tensor, params);
@@ -336,6 +340,7 @@ TEST(TransposeConvTest, SInt16_CWQ_weights)
params.padding = Padding::VALID;
params.stride_height = 2;
params.stride_width = 2;
+ params.activation = luci::FusedActFunc::NONE;
TransposeConv kernel(&output_shape_tensor, &filter_tensor, &input_tensor, &bias_tensor,
&output_tensor, &scratch_tensor, params);
diff --git a/compiler/luci-interpreter/src/loader/KernelBuilder.test.cpp b/compiler/luci-interpreter/src/loader/KernelBuilder.test.cpp
index b221b6921..10a01f418 100644
--- a/compiler/luci-interpreter/src/loader/KernelBuilder.test.cpp
+++ b/compiler/luci-interpreter/src/loader/KernelBuilder.test.cpp
@@ -1319,6 +1319,7 @@ TEST_F(KernelBuilderTest, TransposeConv)
op->padding(luci::Padding::SAME);
op->stride()->h(11);
op->stride()->w(13);
+ op->fusedActivationFunction(luci::FusedActFunc::NONE);
auto kernel = buildKernel<kernels::TransposeConv>(op);
ASSERT_THAT(kernel, NotNull());
@@ -1331,6 +1332,7 @@ TEST_F(KernelBuilderTest, TransposeConv)
EXPECT_THAT(kernel->params().padding, Eq(op->padding()));
EXPECT_THAT(kernel->params().stride_height, Eq(op->stride()->h()));
EXPECT_THAT(kernel->params().stride_width, Eq(op->stride()->w()));
+ EXPECT_THAT(kernel->params().activation, Eq(op->fusedActivationFunction()));
}
TEST_F(KernelBuilderTest, Unpack)
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Floor.cpp b/compiler/luci-interpreter/src/loader/nodes/FloorMod.cpp
index 59164ce9f..a4852f13e 100644
--- a/onert-micro/luci-interpreter/src/loader/nodes/Floor.cpp
+++ b/compiler/luci-interpreter/src/loader/nodes/FloorMod.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,21 +16,22 @@
#include "Builders.h"
-#include "kernels/Floor.h"
+#include "kernels/FloorMod.h"
namespace luci_interpreter
{
-std::unique_ptr<Kernel> build_kernel_CircleFloor(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
+std::unique_ptr<Kernel> build_kernel_CircleFloorMod(const luci::CircleNode *circle_node,
+ KernelBuilderHelper &helper)
{
- assert(inputs.size() == 1);
+ const auto *node = loco::must_cast<const luci::CircleFloorMod *>(circle_node);
+ assert(node->arity() == 2);
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
+ const Tensor *x = helper.getInputTensor(node->x());
+ const Tensor *y = helper.getInputTensor(node->y());
+ Tensor *output = helper.getOutputTensor(node);
- return std::make_unique<kernels::Floor>(input, output);
+ return std::make_unique<kernels::FloorMod>(x, y, output);
}
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/PRelu.cpp b/compiler/luci-interpreter/src/loader/nodes/Gelu.cpp
index 6adc5495b..fc77a5817 100644
--- a/onert-micro/luci-interpreter/src/loader/nodes/PRelu.cpp
+++ b/compiler/luci-interpreter/src/loader/nodes/Gelu.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,22 +16,23 @@
#include "Builders.h"
-#include "kernels/PRelu.h"
+#include "kernels/Gelu.h"
namespace luci_interpreter
{
-std::unique_ptr<Kernel> build_kernel_CirclePRelu(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
+std::unique_ptr<Kernel> build_kernel_CircleGelu(const luci::CircleNode *circle_node,
+ KernelBuilderHelper &helper)
{
- assert(inputs.size() == 2);
+ const auto *node = loco::must_cast<const luci::CircleGelu *>(circle_node);
+ assert(node->arity() == 1);
+ const Tensor *input = helper.getInputTensor(node->features());
+ Tensor *output = helper.getOutputTensor(node);
- const Tensor *input = inputs.at(0);
- const Tensor *alpha = inputs.at(1);
- Tensor *output = outputs.at(0);
+ GeluParams params{};
+ params.approximate = node->approximate();
- return std::make_unique<kernels::PRelu>(input, alpha, output);
+ return std::make_unique<kernels::Gelu>(input, output, params);
}
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/LessEqual.cpp b/compiler/luci-interpreter/src/loader/nodes/HardSwish.cpp
index ca4f26cd3..2e62f2402 100644
--- a/onert-micro/luci-interpreter/src/loader/nodes/LessEqual.cpp
+++ b/compiler/luci-interpreter/src/loader/nodes/HardSwish.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,23 +16,20 @@
#include "Builders.h"
-#include "kernels/LessEqual.h"
+#include "kernels/HardSwish.h"
namespace luci_interpreter
{
-std::unique_ptr<Kernel> build_kernel_CircleLessEqual(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
+std::unique_ptr<Kernel> build_kernel_CircleHardSwish(const luci::CircleNode *circle_node,
+ KernelBuilderHelper &helper)
{
- assert(inputs.size() == 2);
+ const auto *node = loco::must_cast<const luci::CircleHardSwish *>(circle_node);
+ assert(node->arity() == 1);
- const Tensor *x = inputs.at(0);
- const Tensor *y = inputs.at(1);
- Tensor *output = outputs.at(0);
+ const Tensor *input = helper.getInputTensor(node->features());
+ Tensor *output = helper.getOutputTensor(node);
- return std::make_unique<kernels::LessEqual>(x, y, output);
+ return std::make_unique<kernels::HardSwish>(input, output);
}
-
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Exp.cpp b/compiler/luci-interpreter/src/loader/nodes/Log.cpp
index 401b6d064..048e3101e 100644
--- a/onert-micro/luci-interpreter/src/loader/nodes/Exp.cpp
+++ b/compiler/luci-interpreter/src/loader/nodes/Log.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,21 +16,21 @@
#include "Builders.h"
-#include "kernels/Exp.h"
+#include "kernels/Log.h"
namespace luci_interpreter
{
-std::unique_ptr<Kernel> build_kernel_CircleExp(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
+std::unique_ptr<Kernel> build_kernel_CircleLog(const luci::CircleNode *circle_node,
+ KernelBuilderHelper &helper)
{
- assert(inputs.size() == 1);
+ const auto *node = loco::must_cast<const luci::CircleLog *>(circle_node);
+ assert(node->arity() == 1);
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
+ const Tensor *input = helper.getInputTensor(node->x());
+ Tensor *output = helper.getOutputTensor(node);
- return std::make_unique<kernels::Exp>(input, output);
+ return std::make_unique<kernels::Log>(input, output);
}
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Cast.cpp b/compiler/luci-interpreter/src/loader/nodes/Select.cpp
index 441dacbc6..a0f18047b 100644
--- a/onert-micro/luci-interpreter/src/loader/nodes/Cast.cpp
+++ b/compiler/luci-interpreter/src/loader/nodes/Select.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,21 +16,23 @@
#include "Builders.h"
-#include "kernels/Cast.h"
+#include "kernels/Select.h"
namespace luci_interpreter
{
-std::unique_ptr<Kernel> build_kernel_CircleCast(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
+std::unique_ptr<Kernel> build_kernel_CircleSelect(const luci::CircleNode *circle_node,
+ KernelBuilderHelper &helper)
{
- assert(inputs.size() == 1);
+ const auto *node = loco::must_cast<const luci::CircleSelect *>(circle_node);
+ assert(node->arity() == 3);
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
+ const Tensor *c = helper.getInputTensor(node->condition());
+ const Tensor *t = helper.getInputTensor(node->t());
+ const Tensor *e = helper.getInputTensor(node->e());
+ Tensor *output = helper.getOutputTensor(node);
- return std::make_unique<kernels::Cast>(input, output);
+ return std::make_unique<kernels::Select>(c, t, e, output);
}
} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/loader/nodes/Sum.cpp b/compiler/luci-interpreter/src/loader/nodes/Sum.cpp
new file mode 100644
index 000000000..6dfe362c9
--- /dev/null
+++ b/compiler/luci-interpreter/src/loader/nodes/Sum.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Builders.h"
+
+#include "kernels/Sum.h"
+
+namespace luci_interpreter
+{
+
+std::unique_ptr<Kernel> build_kernel_CircleSum(const luci::CircleNode *circle_node,
+ KernelBuilderHelper &helper)
+{
+ const auto *node = loco::must_cast<const luci::CircleSum *>(circle_node);
+ assert(node->arity() == 2);
+
+ const Tensor *input = helper.getInputTensor(node->input());
+ const Tensor *axes = helper.getInputTensor(node->reduction_indices());
+ Tensor *output = helper.getOutputTensor(node);
+
+ auto temp_index_unique =
+ std::make_unique<Tensor>(DataType::S32, Shape({}), AffineQuantization{}, "");
+ temp_index_unique->set_observable(false);
+ temp_index_unique->set_data_buffer(nullptr);
+ Tensor *temp_index =
+ helper.getRuntimeGraph(node->graph())->addTensor(std::move(temp_index_unique));
+
+ auto resolved_axes_unique =
+ std::make_unique<Tensor>(DataType::S32, Shape({}), AffineQuantization{}, "");
+ resolved_axes_unique->set_observable(false);
+ resolved_axes_unique->set_data_buffer(nullptr);
+ Tensor *resolved_axes =
+ helper.getRuntimeGraph(node->graph())->addTensor(std::move(resolved_axes_unique));
+
+ ReducerParams params{};
+ params.keep_dims = node->keep_dims();
+
+ return std::make_unique<kernels::Sum>(input, axes, output, temp_index, resolved_axes, params);
+}
+
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/loader/nodes/TransposeConv.cpp b/compiler/luci-interpreter/src/loader/nodes/TransposeConv.cpp
index d773e301e..72d1aecf7 100644
--- a/compiler/luci-interpreter/src/loader/nodes/TransposeConv.cpp
+++ b/compiler/luci-interpreter/src/loader/nodes/TransposeConv.cpp
@@ -47,6 +47,13 @@ std::unique_ptr<Kernel> build_kernel_CircleTransposeConv(const luci::CircleNode
params.padding = node->padding();
params.stride_height = node->stride()->h();
params.stride_width = node->stride()->w();
+ params.activation = node->fusedActivationFunction();
+
+ // TODO support activation
+ if (params.activation != luci::FusedActFunc::NONE)
+ {
+ throw std::runtime_error("Unsupported activation of TransposeConv");
+ }
return std::make_unique<kernels::TransposeConv>(input_sizes, filter, out_backprop, bias, output,
tmp, params);
diff --git a/compiler/luci-pass-value-test/CMakeLists.txt b/compiler/luci-pass-value-test/CMakeLists.txt
index c86d2cda6..dcd242c6e 100644
--- a/compiler/luci-pass-value-test/CMakeLists.txt
+++ b/compiler/luci-pass-value-test/CMakeLists.txt
@@ -49,18 +49,7 @@ add_test(NAME luci_pass_value_test
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/eval_driver.sh"
"${CMAKE_CURRENT_BINARY_DIR}"
"${ARTIFACTS_BIN_PATH}"
- "${NNCC_OVERLAY_DIR}/venv_2_8_0"
+ "${NNCC_OVERLAY_DIR}/venv_2_12_1"
"$<TARGET_FILE:luci_eval_driver>"
${LUCI_PASS_VALUE_TESTS}
)
-
-if(ONE_UBUNTU_CODENAME_JAMMY)
- add_test(NAME luci_pass_value_210_test
- COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/eval_driver.sh"
- "${CMAKE_CURRENT_BINARY_DIR}"
- "${ARTIFACTS_BIN_PATH}"
- "${NNCC_OVERLAY_DIR}/venv_2_10_1"
- "$<TARGET_FILE:luci_eval_driver>"
- ${LUCI_PASS_VALUE_TESTS}
- )
-endif(ONE_UBUNTU_CODENAME_JAMMY)
diff --git a/compiler/luci-pass-value-test/test.lst b/compiler/luci-pass-value-test/test.lst
index b0b938c1c..93634b2fc 100644
--- a/compiler/luci-pass-value-test/test.lst
+++ b/compiler/luci-pass-value-test/test.lst
@@ -13,6 +13,7 @@ addeval(Net_Conv_Add_Mul_001 fuse_batchnorm_with_conv)
addeval(Net_Conv_Add_Mul_002 fuse_batchnorm_with_conv)
addeval(Net_Conv_Min_Max_000 transform_min_max_to_relu6)
addeval(Net_Conv_Min_Relu_000 transform_min_relu_to_relu6)
+addeval(HardSwish_001 decompose_hardswish)
addeval(Net_Conv_PReluGraph_000 fuse_prelu)
addeval(Net_Conv_Relu6_000 fuse_activation_function)
addeval(Net_Densify_Add_000 fold_densify)
diff --git a/compiler/luci-value-test/CMakeLists.txt b/compiler/luci-value-test/CMakeLists.txt
index b55f60236..be7e881d0 100644
--- a/compiler/luci-value-test/CMakeLists.txt
+++ b/compiler/luci-value-test/CMakeLists.txt
@@ -29,7 +29,7 @@ if(NOT CMAKE_CROSSCOMPILING)
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/evalverify.sh"
"${CMAKE_CURRENT_BINARY_DIR}"
"${ARTIFACTS_BIN_PATH}"
- "${NNCC_OVERLAY_DIR}/venv_2_8_0"
+ "${NNCC_OVERLAY_DIR}/venv_2_12_1"
"$<TARGET_FILE:luci_eval_driver>"
${LUCI_VALUE_TESTS}
)
@@ -39,34 +39,12 @@ if(NOT CMAKE_CROSSCOMPILING)
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/evalverifytol.sh"
"${CMAKE_CURRENT_BINARY_DIR}"
"${ARTIFACTS_BIN_PATH}"
- "${NNCC_OVERLAY_DIR}/venv_2_8_0"
+ "${NNCC_OVERLAY_DIR}/venv_2_12_1"
"$<TARGET_FILE:luci_eval_driver>"
${LUCI_VALUE_TESTS_TOL}
)
endif()
- if(ONE_UBUNTU_CODENAME_JAMMY)
- add_test(NAME luci_value_210_test
- COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/evalverify.sh"
- "${CMAKE_CURRENT_BINARY_DIR}"
- "${ARTIFACTS_BIN_PATH}"
- "${NNCC_OVERLAY_DIR}/venv_2_10_1"
- "$<TARGET_FILE:luci_eval_driver>"
- ${LUCI_VALUE_TESTS}
- )
-
- if(DEFINED LUCI_VALUE_TESTS_TOL)
- add_test(NAME luci_value_tol_210_test
- COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/evalverifytol.sh"
- "${CMAKE_CURRENT_BINARY_DIR}"
- "${ARTIFACTS_BIN_PATH}"
- "${NNCC_OVERLAY_DIR}/venv_2_10_1"
- "$<TARGET_FILE:luci_eval_driver>"
- ${LUCI_VALUE_TESTS_TOL}
- )
- endif()
- endif(ONE_UBUNTU_CODENAME_JAMMY)
-
else(NOT CMAKE_CROSSCOMPILING)
# NOTE target test is carried out using reference input/output data from host
# test results. this is because it would be difficult to prepare
diff --git a/compiler/luci-value-test/test.lst b/compiler/luci-value-test/test.lst
index 70c3fb1f9..3368b6450 100644
--- a/compiler/luci-value-test/test.lst
+++ b/compiler/luci-value-test/test.lst
@@ -33,7 +33,7 @@ addeval(Conv2D_000)
addeval(Conv2D_001)
addeval(Conv2D_002)
addeval(Conv2D_003)
-addeval(Conv2D_U8_000)
+#addeval(Conv2D_U8_000) --> test with tolerance
addeval(Conv2D_U8_001)
#addeval(Cos_000)
addeval(DepthToSpace_000)
@@ -54,16 +54,18 @@ addeval(Exp_000)
addeval(Floor_000)
addeval(FloorDiv_000)
addeval(FloorDiv_001)
-#addeval(FloorMod_000)
-#addeval(FloorMod_001)
+addeval(FloorMod_000)
+addeval(FloorMod_001)
addeval(FullyConnected_000)
addeval(FullyConnected_001)
addeval(FullyConnected_002)
#addeval(FullyConnected_U8_000)
addeval(Gather_000)
#addeval(GatherNd_000)
+addeval(Gelu_000)
#addeval(Greater_000)
addeval(GreaterEqual_000)
+addeval(HardSwish_000)
addeval(If_000)
addeval(If_001)
addeval(L2Normalize_000)
@@ -73,7 +75,7 @@ addeval(LeakyRelu_000)
addeval(Less_000)
addeval(LessEqual_000)
addeval(LocalResponseNormalization_000)
-#addeval(Log_000)
+addeval(Log_000)
addeval(LogicalAnd_000)
addeval(LogicalNot_000)
addeval(LogicalOr_000)
@@ -132,9 +134,9 @@ addeval(ResizeNearestNeighbor_000)
addeval(Rsqrt_000)
#addeval(ScatterNd_000)
#addeval(SegmentSum_000)
-#addeval(Select_000)
-#addeval(Select_001)
-#addeval(Select_002)
+addeval(Select_000)
+addeval(Select_001)
+addeval(Select_002)
#addeval(SelectV2_000)
#addeval(SelectV2_001)
#addeval(SelectV2_002)
@@ -165,8 +167,8 @@ addeval(StridedSlice_003)
addeval(StridedSlice_004)
addeval(Sub_000)
addeval(Sub_U8_000)
-#addeval(Sum_000)
-#addeval(Sum_001)
+addeval(Sum_000)
+addeval(Sum_001)
addeval(Tanh_000)
#addeval(Tile_000)
#addeval(Tile_U8_000)
@@ -197,5 +199,8 @@ addeval(Part_While_001)
# Tests with tolerance
addevaltol(SVDF_000 8e-3 8e-3)
addevaltol(SVDF_001 8e-3 8e-3)
+# TODO fix Conv2D_U8_000 to test without tolerenace
+# refer https://github.com/Samsung/ONE/issues/11255#issuecomment-1685424361
+addeval(Conv2D_U8_000 1 1)
# refer https://github.com/Samsung/ONE/issues/10438
addevaltol(YUV_TO_RGB_U8_000 1 1)
diff --git a/compiler/luci/export/CMakeLists.txt b/compiler/luci/export/CMakeLists.txt
index f46181eb6..fb0e20e00 100644
--- a/compiler/luci/export/CMakeLists.txt
+++ b/compiler/luci/export/CMakeLists.txt
@@ -12,7 +12,7 @@ target_include_directories(luci_export PUBLIC include)
target_link_libraries(luci_export PRIVATE luci_lang)
target_link_libraries(luci_export PRIVATE luci_service)
target_link_libraries(luci_export PRIVATE luci_pass)
-target_link_libraries(luci_export PRIVATE mio_circle04)
+target_link_libraries(luci_export PRIVATE mio_circle06)
target_link_libraries(luci_export PRIVATE luci_env)
target_link_libraries(luci_export PRIVATE luci_log)
target_link_libraries(luci_export PRIVATE luci_logex)
@@ -36,6 +36,6 @@ target_include_directories(luci_export_test PRIVATE src)
target_link_libraries(luci_export_test luci_export)
target_link_libraries(luci_export_test luci_plan)
target_link_libraries(luci_export_test luci_lang)
-target_link_libraries(luci_export_test mio_circle04)
+target_link_libraries(luci_export_test mio_circle06)
target_link_libraries(luci_export_test luci_env)
target_link_libraries(luci_export_test oops)
diff --git a/compiler/luci/export/src/CircleBuiltinTypesExtractor.h b/compiler/luci/export/src/CircleBuiltinTypesExtractor.h
index 7516197c0..811373ffe 100644
--- a/compiler/luci/export/src/CircleBuiltinTypesExtractor.h
+++ b/compiler/luci/export/src/CircleBuiltinTypesExtractor.h
@@ -187,6 +187,10 @@ public:
{
return circle::CreateGatherNdOptions(_builder).Union();
}
+ flatbuffers::Offset<void> visit(luci::CircleGelu *node)
+ {
+ return circle::CreateGeluOptions(_builder, node->approximate()).Union();
+ }
flatbuffers::Offset<void> visit(luci::CircleGreater *)
{
return circle::CreateGreaterOptions(_builder).Union();
@@ -195,6 +199,7 @@ public:
{
return circle::CreateGreaterEqualOptions(_builder).Union();
}
+ flatbuffers::Offset<void> visit(luci::CircleHardSwish *) { return _no_option; }
flatbuffers::Offset<void> visit(luci::CircleIf *node)
{
return circle::CreateIfOptions(_builder, node->then_branch(), node->else_branch()).Union();
@@ -480,7 +485,8 @@ public:
flatbuffers::Offset<void> visit(luci::CircleTransposeConv *node)
{
return circle::CreateTransposeConvOptions(_builder, getOpPadding(node->padding()),
- node->stride()->w(), node->stride()->h())
+ node->stride()->w(), node->stride()->h(),
+ to_circle_actfunc(node->fusedActivationFunction()))
.Union();
}
flatbuffers::Offset<void> visit(luci::CircleUnidirectionalSequenceLSTM *node)
diff --git a/compiler/luci/export/src/CircleOps.lst b/compiler/luci/export/src/CircleOps.lst
index 8a75ef706..a047f29d7 100644
--- a/compiler/luci/export/src/CircleOps.lst
+++ b/compiler/luci/export/src/CircleOps.lst
@@ -49,8 +49,10 @@ CIRCLE_NODE(CircleFloorMod, BuiltinOperator_FLOOR_MOD, BuiltinOptions_FloorModOp
CIRCLE_NODE(CircleFullyConnected, BuiltinOperator_FULLY_CONNECTED, BuiltinOptions_FullyConnectedOptions)
CIRCLE_NODE(CircleGather, BuiltinOperator_GATHER, BuiltinOptions_GatherOptions)
CIRCLE_NODE(CircleGatherNd, BuiltinOperator_GATHER_ND, BuiltinOptions_GatherNdOptions)
+CIRCLE_NODE(CircleGelu, BuiltinOperator_GELU, BuiltinOptions_GeluOptions)
CIRCLE_NODE(CircleGreater, BuiltinOperator_GREATER, BuiltinOptions_GreaterOptions)
CIRCLE_NODE(CircleGreaterEqual, BuiltinOperator_GREATER_EQUAL, BuiltinOptions_GreaterEqualOptions)
+CIRCLE_NODE(CircleHardSwish, BuiltinOperator_HARD_SWISH, BuiltinOptions_NONE)
CIRCLE_NODE(CircleIf, BuiltinOperator_IF, BuiltinOptions_IfOptions)
CIRCLE_NODE(CircleL2Normalize, BuiltinOperator_L2_NORMALIZATION, BuiltinOptions_L2NormOptions)
CIRCLE_NODE(CircleL2Pool2D, BuiltinOperator_L2_POOL_2D, BuiltinOptions_Pool2DOptions)
diff --git a/compiler/luci/import/CMakeLists.txt b/compiler/luci/import/CMakeLists.txt
index bc0a00b34..2e7e88118 100644
--- a/compiler/luci/import/CMakeLists.txt
+++ b/compiler/luci/import/CMakeLists.txt
@@ -12,7 +12,7 @@ target_include_directories(luci_import PUBLIC include)
target_link_libraries(luci_import PUBLIC luci_lang)
target_link_libraries(luci_import PUBLIC luci_profile)
target_link_libraries(luci_import PUBLIC luci_plan)
-target_link_libraries(luci_import PUBLIC mio_circle04)
+target_link_libraries(luci_import PUBLIC mio_circle06)
target_link_libraries(luci_import PRIVATE luci_env)
target_link_libraries(luci_import PRIVATE luci_log)
target_link_libraries(luci_import PRIVATE luci_logex)
@@ -20,7 +20,7 @@ target_link_libraries(luci_import PRIVATE nncc_common)
target_link_libraries(luci_import PRIVATE locop)
target_link_libraries(luci_import PRIVATE foder)
target_link_libraries(luci_import PRIVATE oops)
-target_link_libraries(luci_import PRIVATE mio_circle04_helper)
+target_link_libraries(luci_import PRIVATE mio_circle06_helper)
install(TARGETS luci_import DESTINATION lib)
install(DIRECTORY include/ DESTINATION include
FILES_MATCHING PATTERN "*.h")
diff --git a/compiler/luci/import/include/luci/Import/NodeBuilder.h b/compiler/luci/import/include/luci/Import/NodeBuilder.h
index 440b491b0..05f533f38 100644
--- a/compiler/luci/import/include/luci/Import/NodeBuilder.h
+++ b/compiler/luci/import/include/luci/Import/NodeBuilder.h
@@ -42,6 +42,7 @@ class NodeBuilderBase
public:
virtual CircleNode *build(TensorIndex tensor_idx, GraphBuilderContext *context) const = 0;
virtual NodeBuilderType builder_type() const = 0;
+ virtual ~NodeBuilderBase() = default;
};
/**
diff --git a/compiler/luci/import/include/luci/Import/Nodes.h b/compiler/luci/import/include/luci/Import/Nodes.h
index a4a6d7ce8..e8c8d0aae 100644
--- a/compiler/luci/import/include/luci/Import/Nodes.h
+++ b/compiler/luci/import/include/luci/Import/Nodes.h
@@ -52,8 +52,10 @@
#include "Nodes/CircleFullyConnected.h"
#include "Nodes/CircleGather.h"
#include "Nodes/CircleGatherNd.h"
+#include "Nodes/CircleGelu.h"
#include "Nodes/CircleGreater.h"
#include "Nodes/CircleGreaterEqual.h"
+#include "Nodes/CircleHardSwish.h"
#include "Nodes/CircleIf.h"
#include "Nodes/CircleInstanceNorm.h"
#include "Nodes/CircleL2Normalize.h"
diff --git a/compiler/luci/import/include/luci/Import/Nodes/CircleGelu.h b/compiler/luci/import/include/luci/Import/Nodes/CircleGelu.h
new file mode 100644
index 000000000..9be266fb1
--- /dev/null
+++ b/compiler/luci/import/include/luci/Import/Nodes/CircleGelu.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_IMPORT_OP_CIRCLE_GELU_H__
+#define __LUCI_IMPORT_OP_CIRCLE_GELU_H__
+
+#include "luci/Import/GraphBuilder.h"
+
+namespace luci
+{
+
+class CircleGeluGraphBuilder : public GraphBuilder
+{
+public:
+ bool validate(const ValidateArgs &args) const final;
+
+private:
+ CircleNode *build_node(const circle::OperatorT &op, const std::vector<CircleNode *> &inputs,
+ loco::Graph *graph) const final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_IMPORT_OP_CIRCLE_GELU_H__
diff --git a/compiler/luci/import/include/luci/Import/Nodes/CircleHardSwish.h b/compiler/luci/import/include/luci/Import/Nodes/CircleHardSwish.h
new file mode 100644
index 000000000..7aeb0299b
--- /dev/null
+++ b/compiler/luci/import/include/luci/Import/Nodes/CircleHardSwish.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_IMPORT_OP_CIRCLE_HARDSWISH_H__
+#define __LUCI_IMPORT_OP_CIRCLE_HARDSWISH_H__
+
+#include "luci/Import/GraphBuilder.h"
+
+namespace luci
+{
+
+class CircleHardSwishGraphBuilder : public GraphBuilder
+{
+public:
+ bool validate(const ValidateArgs &args) const final;
+
+private:
+ CircleNode *build_node(const circle::OperatorT &op, const std::vector<CircleNode *> &inputs,
+ loco::Graph *graph) const final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_IMPORT_OP_CIRCLE_HARDSWISH_H__
diff --git a/compiler/luci/import/src/GraphBuilderRegistry.cpp b/compiler/luci/import/src/GraphBuilderRegistry.cpp
index d3b52aadb..9c868320d 100644
--- a/compiler/luci/import/src/GraphBuilderRegistry.cpp
+++ b/compiler/luci/import/src/GraphBuilderRegistry.cpp
@@ -61,13 +61,15 @@ GraphBuilderRegistry::GraphBuilderRegistry()
CIRCLE_NODE(FULLY_CONNECTED, CircleFullyConnectedGraphBuilder); // 9
CIRCLE_NODE(GATHER, CircleGatherGraphBuilder); // 36
CIRCLE_NODE(GATHER_ND, CircleGatherNdGraphBuilder); // 107
+ CIRCLE_NODE(GELU, CircleGeluGraphBuilder); // 150
CIRCLE_NODE(GREATER, CircleGreaterGraphBuilder); // 61
CIRCLE_NODE(GREATER_EQUAL, CircleGreaterEqualGraphBuilder); // 62
+ CIRCLE_NODE(HARD_SWISH, CircleHardSwishGraphBuilder); // 117
CIRCLE_NODE(IF, CircleIfGraphBuilder); // 118
CIRCLE_NODE(INSTANCE_NORM, CircleInstanceNormGraphBuilder); // 254
CIRCLE_NODE(L2_NORMALIZATION, CircleL2NormalizeGraphBuilder); // 11
CIRCLE_NODE(L2_POOL_2D, CircleL2Pool2DGraphBuilder); // 12
- CIRCLE_NODE(LEAKY_RELU, CircleLeakyReluGraphBuilder); // 98,
+ CIRCLE_NODE(LEAKY_RELU, CircleLeakyReluGraphBuilder); // 98
CIRCLE_NODE(LESS, CircleLessGraphBuilder); // 58
CIRCLE_NODE(LESS_EQUAL, CircleLessEqualGraphBuilder); // 63
CIRCLE_NODE(LOCAL_RESPONSE_NORMALIZATION, CircleLocalResponseNormalizationGraphBuilder); // 13
@@ -86,16 +88,16 @@ GraphBuilderRegistry::GraphBuilderRegistry()
CIRCLE_NODE(MIRROR_PAD, CircleMirrorPadGraphBuilder); // 100
CIRCLE_NODE(MUL, CircleMulGraphBuilder); // 18
CIRCLE_NODE(NEG, CircleNegGraphBuilder); // 59
- CIRCLE_NODE(NON_MAX_SUPPRESSION_V4, CircleNonMaxSuppressionV4GraphBuilder); // 120,
- CIRCLE_NODE(NON_MAX_SUPPRESSION_V5, CircleNonMaxSuppressionV5GraphBuilder); // 121,
+ CIRCLE_NODE(NON_MAX_SUPPRESSION_V4, CircleNonMaxSuppressionV4GraphBuilder); // 120
+ CIRCLE_NODE(NON_MAX_SUPPRESSION_V5, CircleNonMaxSuppressionV5GraphBuilder); // 121
CIRCLE_NODE(NOT_EQUAL, CircleNotEqualGraphBuilder); // 72
CIRCLE_NODE(ONE_HOT, CircleOneHotGraphBuilder); // 85
CIRCLE_NODE(PACK, CirclePackGraphBuilder); // 83
CIRCLE_NODE(PAD, CirclePadGraphBuilder); // 34
CIRCLE_NODE(PADV2, CirclePadV2GraphBuilder); // 60
CIRCLE_NODE(POW, CirclePowGraphBuilder); // 78
- CIRCLE_NODE(PRELU, CirclePReluGraphBuilder); // 54,
- CIRCLE_NODE(QUANTIZE, CircleQuantizeGraphBuilder); // 114,
+ CIRCLE_NODE(PRELU, CirclePReluGraphBuilder); // 54
+ CIRCLE_NODE(QUANTIZE, CircleQuantizeGraphBuilder); // 114
CIRCLE_NODE(RANGE, CircleRangeGraphBuilder); // 96
CIRCLE_NODE(RANK, CircleRankGraphBuilder); // 110
CIRCLE_NODE(REDUCE_ANY, CircleReduceAnyGraphBuilder); // 91
@@ -160,7 +162,6 @@ GraphBuilderRegistry::GraphBuilderRegistry()
// BuiltinOperator_BIDIRECTIONAL_SEQUENCE_RNN = 46,
// BuiltinOperator_DELEGATE = 51,
// BuiltinOperator_ARG_MAX = 56,
- // BuiltinOperator_HARD_SWISH = 117,
// Register builders for nodes which not handles in builders registered above.
#define CIRCLE_NODE(CLASS) add(std::make_unique<CLASS>())
diff --git a/compiler/luci/import/src/Nodes/CircleGelu.cpp b/compiler/luci/import/src/Nodes/CircleGelu.cpp
new file mode 100644
index 000000000..89b325f82
--- /dev/null
+++ b/compiler/luci/import/src/Nodes/CircleGelu.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Import/Nodes/CircleGelu.h"
+
+#include <luci/IR/Nodes/CircleGelu.h>
+
+#include <loco.h>
+
+namespace luci
+{
+
+bool CircleGeluGraphBuilder::validate(const ValidateArgs &args) const
+{
+ return GraphBuilder::validate(args, 1);
+}
+
+CircleNode *CircleGeluGraphBuilder::build_node(const circle::OperatorT &op,
+ const std::vector<CircleNode *> &inputs,
+ loco::Graph *graph) const
+{
+ auto *node = graph->nodes()->create<CircleGelu>();
+ node->features(inputs.at(0));
+
+ const auto *options = op.builtin_options.AsGeluOptions();
+ node->approximate(options->approximate);
+
+ return node;
+}
+
+} // namespace luci
diff --git a/compiler/luci/import/src/Nodes/CircleHardSwish.cpp b/compiler/luci/import/src/Nodes/CircleHardSwish.cpp
new file mode 100644
index 000000000..47fc1c92c
--- /dev/null
+++ b/compiler/luci/import/src/Nodes/CircleHardSwish.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Import/Nodes/CircleHardSwish.h"
+
+#include <luci/IR/Nodes/CircleHardSwish.h>
+
+#include <loco.h>
+
+namespace luci
+{
+
+bool CircleHardSwishGraphBuilder::validate(const ValidateArgs &args) const
+{
+ return GraphBuilder::validate(args, 1);
+}
+
+CircleNode *CircleHardSwishGraphBuilder::build_node(const circle::OperatorT &,
+ const std::vector<CircleNode *> &inputs,
+ loco::Graph *graph) const
+{
+ auto *node = graph->nodes()->create<CircleHardSwish>();
+ node->features(inputs.at(0));
+
+ return node;
+}
+
+} // namespace luci
diff --git a/compiler/luci/import/src/Nodes/CircleReshape.cpp b/compiler/luci/import/src/Nodes/CircleReshape.cpp
index 3421620ce..12da54ef7 100644
--- a/compiler/luci/import/src/Nodes/CircleReshape.cpp
+++ b/compiler/luci/import/src/Nodes/CircleReshape.cpp
@@ -30,7 +30,7 @@ bool CircleReshapeGraphBuilder::validate(const ValidateArgs &args) const
if (args.op.outputs.size() != 1)
return false;
- // for two inputs, check if type is S32
+ // for two inputs, check if type is S32 or S64
if (args.op.inputs.size() == 2)
{
const auto &inputs = args.op.inputs;
@@ -38,9 +38,8 @@ bool CircleReshapeGraphBuilder::validate(const ValidateArgs &args) const
const auto tensor_in = tensors.at(inputs.at(1));
assert(tensor_in != nullptr);
- // NOTE fix this if there is any other case
- // TensorFlow lite and circle only supports S32
- if (tensor_in->type() != circle::TensorType::TensorType_INT32)
+ if (tensor_in->type() != circle::TensorType::TensorType_INT32 &&
+ tensor_in->type() != circle::TensorType::TensorType_INT64)
return false;
}
diff --git a/compiler/luci/import/src/Nodes/CircleTransposeConv.cpp b/compiler/luci/import/src/Nodes/CircleTransposeConv.cpp
index 01a28cb8a..62326f435 100644
--- a/compiler/luci/import/src/Nodes/CircleTransposeConv.cpp
+++ b/compiler/luci/import/src/Nodes/CircleTransposeConv.cpp
@@ -74,6 +74,7 @@ CircleNode *CircleTransposeConvGraphBuilder::build_node(const circle::OperatorT
node->padding(luci_padding(options->padding));
node->stride()->w(options->stride_w);
node->stride()->h(options->stride_h);
+ node->fusedActivationFunction(luci_actfunc(options->fused_activation_function));
return node;
}
diff --git a/compiler/luci/lang/include/luci/IR/CircleNodes.h b/compiler/luci/lang/include/luci/IR/CircleNodes.h
index 901f1cbca..d643b0893 100644
--- a/compiler/luci/lang/include/luci/IR/CircleNodes.h
+++ b/compiler/luci/lang/include/luci/IR/CircleNodes.h
@@ -49,8 +49,10 @@
#include "Nodes/CircleFullyConnected.h"
#include "Nodes/CircleGather.h"
#include "Nodes/CircleGatherNd.h"
+#include "Nodes/CircleGelu.h"
#include "Nodes/CircleGreater.h"
#include "Nodes/CircleGreaterEqual.h"
+#include "Nodes/CircleHardSwish.h"
#include "Nodes/CircleIf.h"
#include "Nodes/CircleL2Normalize.h"
#include "Nodes/CircleL2Pool2D.h"
diff --git a/compiler/luci/lang/include/luci/IR/CircleNodes.lst b/compiler/luci/lang/include/luci/IR/CircleNodes.lst
index f227a03f5..1646909e8 100644
--- a/compiler/luci/lang/include/luci/IR/CircleNodes.lst
+++ b/compiler/luci/lang/include/luci/IR/CircleNodes.lst
@@ -47,8 +47,10 @@ CIRCLE_NODE(FLOOR_MOD, CircleFloorMod)
CIRCLE_NODE(FULLY_CONNECTED, CircleFullyConnected)
CIRCLE_NODE(GATHER, CircleGather)
CIRCLE_NODE(GATHER_ND, CircleGatherNd)
+CIRCLE_NODE(GELU, CircleGelu)
CIRCLE_NODE(GREATER, CircleGreater)
CIRCLE_NODE(GREATER_EQUAL, CircleGreaterEqual)
+CIRCLE_NODE(HARD_SWISH, CircleHardSwish)
CIRCLE_NODE(IF, CircleIf)
CIRCLE_NODE(L2_NORMALIZATION, CircleL2Normalize)
CIRCLE_NODE(L2_POOL_2D, CircleL2Pool2D)
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleGelu.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleGelu.h
new file mode 100644
index 000000000..badfec7cf
--- /dev/null
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleGelu.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_IR_CIRCLEGELU_H__
+#define __LUCI_IR_CIRCLEGELU_H__
+
+#include "luci/IR/CircleNodeDecl.h"
+#include "luci/IR/CircleOpcode.h"
+
+#include "luci/IR/CircleNodeMixins.h"
+
+namespace luci
+{
+
+/**
+ * @brief GELU in Circle
+ */
+class CircleGelu final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::GELU>>
+{
+public:
+ loco::Node *features(void) const { return at(0)->node(); }
+ void features(loco::Node *node) { at(0)->node(node); }
+
+public:
+ bool approximate(void) const { return _approximate; }
+ void approximate(bool arg) { _approximate = arg; }
+
+private:
+ bool _approximate{false};
+};
+
+} // namespace luci
+
+#endif // __LUCI_IR_CIRCLEGELU_H__
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleHardSwish.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleHardSwish.h
new file mode 100644
index 000000000..18652a07d
--- /dev/null
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleHardSwish.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_IR_CIRCLEHARDSWISH_H__
+#define __LUCI_IR_CIRCLEHARDSWISH_H__
+
+#include "luci/IR/CircleNodeDecl.h"
+#include "luci/IR/CircleOpcode.h"
+
+#include "luci/IR/CircleNodeMixins.h"
+
+namespace luci
+{
+
+/**
+ * @brief HardSwish in Circle
+ */
+class CircleHardSwish final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::HARD_SWISH>>
+{
+public:
+ loco::Node *features(void) const { return at(0)->node(); }
+ void features(loco::Node *node) { at(0)->node(node); }
+};
+
+} // namespace luci
+
+#endif // __LUCI_IR_CIRCLEHARDSWISH_H__
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleTransposeConv.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleTransposeConv.h
index 5ae41c0c4..8c6f04a58 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleTransposeConv.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleTransposeConv.h
@@ -35,6 +35,7 @@ namespace luci
*/
class CircleTransposeConv final
: public FixedArityNode<4, CircleNodeImpl<CircleOpcode::TRANSPOSE_CONV>>,
+ public CircleNodeMixin<CircleNodeTrait::FusedActFunc>,
public CircleNodeMixin<CircleNodeTrait::Bias>
{
public:
diff --git a/compiler/luci/lang/src/Nodes/CircleGelu.test.cpp b/compiler/luci/lang/src/Nodes/CircleGelu.test.cpp
new file mode 100644
index 000000000..b10a2b48b
--- /dev/null
+++ b/compiler/luci/lang/src/Nodes/CircleGelu.test.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/IR/Nodes/CircleGelu.h"
+
+#include "luci/IR/CircleDialect.h"
+#include "luci/IR/CircleNodeVisitor.h"
+
+#include <gtest/gtest.h>
+
+TEST(CircleGeluTest, constructor)
+{
+ luci::CircleGelu gelu_node;
+
+ ASSERT_EQ(luci::CircleDialect::get(), gelu_node.dialect());
+ ASSERT_EQ(luci::CircleOpcode::GELU, gelu_node.opcode());
+
+ ASSERT_EQ(nullptr, gelu_node.features());
+
+ ASSERT_EQ(false, gelu_node.approximate());
+}
+
+TEST(CircleGeluTest, input_NEG)
+{
+ luci::CircleGelu gelu_node;
+ luci::CircleGelu node;
+
+ gelu_node.features(&node);
+ ASSERT_NE(nullptr, gelu_node.features());
+
+ gelu_node.features(nullptr);
+ ASSERT_EQ(nullptr, gelu_node.features());
+
+ gelu_node.approximate(true);
+ ASSERT_NE(false, gelu_node.approximate());
+}
+
+TEST(CircleGeluTest, arity_NEG)
+{
+ luci::CircleGelu gelu_node;
+
+ ASSERT_NO_THROW(gelu_node.arg(0));
+ ASSERT_THROW(gelu_node.arg(1), std::out_of_range);
+}
+
+TEST(CircleGeluTest, visit_mutable_NEG)
+{
+ struct TestVisitor final : public luci::CircleNodeMutableVisitor<void>
+ {
+ };
+
+ luci::CircleGelu gelu_node;
+
+ TestVisitor tv;
+ ASSERT_THROW(gelu_node.accept(&tv), std::exception);
+}
+
+TEST(CircleGeluTest, visit_NEG)
+{
+ struct TestVisitor final : public luci::CircleNodeVisitor<void>
+ {
+ };
+
+ luci::CircleGelu gelu_node;
+
+ TestVisitor tv;
+ ASSERT_THROW(gelu_node.accept(&tv), std::exception);
+}
diff --git a/compiler/luci/lang/src/Nodes/CircleHardSwish.test.cpp b/compiler/luci/lang/src/Nodes/CircleHardSwish.test.cpp
new file mode 100644
index 000000000..7825ce75b
--- /dev/null
+++ b/compiler/luci/lang/src/Nodes/CircleHardSwish.test.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/IR/Nodes/CircleHardSwish.h"
+
+#include "luci/IR/CircleDialect.h"
+#include "luci/IR/CircleNodeVisitor.h"
+
+#include <gtest/gtest.h>
+
+TEST(CircleHardSwishTest, constructor_P)
+{
+ luci::CircleHardSwish hard_swish_node;
+
+ ASSERT_EQ(luci::CircleDialect::get(), hard_swish_node.dialect());
+ ASSERT_EQ(luci::CircleOpcode::HARD_SWISH, hard_swish_node.opcode());
+
+ ASSERT_EQ(nullptr, hard_swish_node.features());
+}
+
+TEST(CircleHardSwishTest, input_NEG)
+{
+ luci::CircleHardSwish hard_swish_node;
+ luci::CircleHardSwish node;
+
+ hard_swish_node.features(&node);
+ ASSERT_NE(nullptr, hard_swish_node.features());
+
+ hard_swish_node.features(nullptr);
+ ASSERT_EQ(nullptr, hard_swish_node.features());
+}
+
+TEST(CircleHardSwishTest, arity_NEG)
+{
+ luci::CircleHardSwish hard_swish_node;
+
+ ASSERT_NO_THROW(hard_swish_node.arg(0));
+ ASSERT_THROW(hard_swish_node.arg(1), std::out_of_range);
+}
+
+TEST(CircleHardSwishTest, visit_mutable_NEG)
+{
+ struct TestVisitor final : public luci::CircleNodeMutableVisitor<void>
+ {
+ };
+
+ luci::CircleHardSwish hard_swish_node;
+
+ TestVisitor tv;
+ ASSERT_THROW(hard_swish_node.accept(&tv), std::exception);
+}
+
+TEST(CircleHardSwishTest, visit_NEG)
+{
+ struct TestVisitor final : public luci::CircleNodeVisitor<void>
+ {
+ };
+
+ luci::CircleHardSwish hard_swish_node;
+
+ TestVisitor tv;
+ ASSERT_THROW(hard_swish_node.accept(&tv), std::exception);
+}
diff --git a/compiler/luci/logex/src/CircleNodeSummaryBuilder.cpp b/compiler/luci/logex/src/CircleNodeSummaryBuilder.cpp
index 8409f250e..e7f38d07b 100644
--- a/compiler/luci/logex/src/CircleNodeSummaryBuilder.cpp
+++ b/compiler/luci/logex/src/CircleNodeSummaryBuilder.cpp
@@ -61,6 +61,19 @@ bool CircleNodeSummaryBuilder::build(const loco::Node *node, const locop::Symbol
return ss.str();
};
+ auto shape_to_str = [](const luci::CircleNode *node) {
+ std::stringstream ss;
+ ss << "<";
+ for (uint32_t i = 0; i < node->rank(); ++i)
+ {
+ if (i)
+ ss << ",";
+ ss << (node->dim(i).known() ? node->dim(i).value() : -1);
+ }
+ ss << ">";
+ return ss.str();
+ };
+
auto circle_node = loco::must_cast<const luci::CircleNode *>(node);
if (const auto builder = create_builder(circle_node))
{
@@ -79,7 +92,8 @@ bool CircleNodeSummaryBuilder::build(const loco::Node *node, const locop::Symbol
builder->update_status(s);
s.opname(circle_opname(circle_node->opcode()));
- s.comments().append("[" + circle_node->name() + "] = " + ptr_to_str(node));
+ s.comments().append("[" + circle_node->name() + " " + shape_to_str(circle_node) +
+ "] = " + ptr_to_str(node));
return true;
}
@@ -154,8 +168,10 @@ CircleNodeSummaryBuilder::create_builder(const luci::CircleNode *node)
CIRCLE_NODE(FULLY_CONNECTED, CircleFullyConnectedSummaryBuilder)
CIRCLE_NODE(GATHER, CircleGatherSummaryBuilder)
CIRCLE_NODE(GATHER_ND, CircleGatherNdSummaryBuilder)
+ CIRCLE_NODE(GELU, CircleGeluSummaryBuilder)
CIRCLE_NODE(GREATER, CircleGreaterSummaryBuilder)
CIRCLE_NODE(GREATER_EQUAL, CircleGreaterEqualSummaryBuilder)
+ CIRCLE_NODE(HARD_SWISH, CircleHardSwishSummaryBuilder)
CIRCLE_NODE(IF, CircleIfSummaryBuilder)
CIRCLE_NODE(INSTANCE_NORM, CircleInstanceNormSummaryBuilder)
CIRCLE_NODE(L2_NORMALIZATION, CircleL2NormalizeSummaryBuilder)
diff --git a/compiler/luci/logex/src/CircleNodeSummaryBuilder.test.cpp b/compiler/luci/logex/src/CircleNodeSummaryBuilder.test.cpp
index 89ea213e0..ae76badc6 100644
--- a/compiler/luci/logex/src/CircleNodeSummaryBuilder.test.cpp
+++ b/compiler/luci/logex/src/CircleNodeSummaryBuilder.test.cpp
@@ -298,6 +298,7 @@ TEST_F(CircleNodeSummaryBuilderTest, TransposeConv_validate)
{
luci::CircleTransposeConv node;
node.padding(luci::Padding::SAME);
+ node.fusedActivationFunction(luci::FusedActFunc::RELU);
EXPECT_TRUE(mock_build(&node));
}
@@ -307,3 +308,10 @@ TEST_F(CircleNodeSummaryBuilderTest, TransposeConv_validate_padding_NEG)
node.padding(luci::Padding::UNDEFINED);
EXPECT_FALSE(mock_build(&node));
}
+
+TEST_F(CircleNodeSummaryBuilderTest, TransposeConv_validate_fused_NEG)
+{
+ luci::CircleTransposeConv node;
+ node.fusedActivationFunction(luci::FusedActFunc::UNDEFINED);
+ EXPECT_FALSE(mock_build(&node));
+}
diff --git a/compiler/luci/logex/src/CircleNodeSummaryBuilders.cpp b/compiler/luci/logex/src/CircleNodeSummaryBuilders.cpp
index 42f11be1e..aba6a8681 100644
--- a/compiler/luci/logex/src/CircleNodeSummaryBuilders.cpp
+++ b/compiler/luci/logex/src/CircleNodeSummaryBuilders.cpp
@@ -539,6 +539,12 @@ std::vector<std::string> CircleGatherNdSummaryBuilder::get_input_names(const luc
return {"params", "indices"};
}
+void CircleGeluSummaryBuilder::build_attributes(const luci::CircleNode *node, locop::NodeSummary &s)
+{
+ auto gelu = loco::must_cast<const luci::CircleGelu *>(node);
+ s.args().append("approximate", to_str(gelu->approximate()));
+}
+
std::vector<std::string> CircleIfSummaryBuilder::get_input_names(const luci::CircleNode *node)
{
auto circle_if = loco::must_cast<const luci::CircleIf *>(node);
@@ -1012,6 +1018,8 @@ bool CircleTransposeConvSummaryBuilder::validate(const luci::CircleNode *node)
auto transpose_conv = loco::must_cast<const luci::CircleTransposeConv *>(node);
if (transpose_conv->padding() == luci::Padding::UNDEFINED)
return false;
+ if (transpose_conv->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
+ return false;
return true;
}
@@ -1028,6 +1036,7 @@ void CircleTransposeConvSummaryBuilder::build_attributes(const luci::CircleNode
auto transpose_conv = loco::must_cast<const luci::CircleTransposeConv *>(node);
s.args().append("stride(h,w)", to_str(transpose_conv->stride()));
s.args().append("padding", to_str(transpose_conv->padding()));
+ s.args().append("fused_activation_function", to_str(transpose_conv->fusedActivationFunction()));
}
std::vector<std::string>
diff --git a/compiler/luci/logex/src/CircleNodeSummaryBuilders.h b/compiler/luci/logex/src/CircleNodeSummaryBuilders.h
index f0cac4e5e..0bdb05d8d 100644
--- a/compiler/luci/logex/src/CircleNodeSummaryBuilders.h
+++ b/compiler/luci/logex/src/CircleNodeSummaryBuilders.h
@@ -280,6 +280,12 @@ private:
std::vector<std::string> get_input_names(const luci::CircleNode *);
};
+class CircleGeluSummaryBuilder final : public CircleNodeWithFEATURESSummaryBuilder
+{
+private:
+ void build_attributes(const luci::CircleNode *node, locop::NodeSummary &s);
+};
+
class CircleGreaterSummaryBuilder final : public CircleNodeWithXYSummaryBuilder
{
};
@@ -288,6 +294,10 @@ class CircleGreaterEqualSummaryBuilder final : public CircleNodeWithXYSummaryBui
{
};
+class CircleHardSwishSummaryBuilder final : public CircleNodeWithFEATURESSummaryBuilder
+{
+};
+
class CircleIfSummaryBuilder final : public CircleNodeSummaryBuilder
{
private:
diff --git a/compiler/luci/partition/CMakeLists.txt b/compiler/luci/partition/CMakeLists.txt
index f28207df2..304ef6307 100644
--- a/compiler/luci/partition/CMakeLists.txt
+++ b/compiler/luci/partition/CMakeLists.txt
@@ -13,7 +13,7 @@ target_link_libraries(luci_partition PUBLIC luci_lang)
target_link_libraries(luci_partition PRIVATE luci_service)
target_link_libraries(luci_partition PRIVATE luci_log)
target_link_libraries(luci_partition PRIVATE luci_logex)
-target_link_libraries(luci_partition PRIVATE mio_circle04)
+target_link_libraries(luci_partition PRIVATE mio_circle06)
target_link_libraries(luci_partition PRIVATE nncc_common)
target_link_libraries(luci_partition PRIVATE pepper_csv2vec)
target_link_libraries(luci_partition PRIVATE oops)
diff --git a/compiler/luci/partition/include/luci/ConnectNode.h b/compiler/luci/partition/include/luci/ConnectNode.h
index 2d9d41d77..d8cbfc6c4 100644
--- a/compiler/luci/partition/include/luci/ConnectNode.h
+++ b/compiler/luci/partition/include/luci/ConnectNode.h
@@ -94,8 +94,10 @@ public:
void visit(const luci::CircleFullyConnected *) final;
void visit(const luci::CircleGather *) final;
void visit(const luci::CircleGatherNd *) final;
+ void visit(const luci::CircleGelu *) final;
void visit(const luci::CircleGreater *) final;
void visit(const luci::CircleGreaterEqual *) final;
+ void visit(const luci::CircleHardSwish *) final;
void visit(const luci::CircleIf *) final;
void visit(const luci::CircleL2Normalize *) final;
void visit(const luci::CircleL2Pool2D *) final;
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/While.cpp b/compiler/luci/partition/src/Nodes/CircleGelu.cpp
index b1f719efc..74ef51cc8 100644
--- a/onert-micro/luci-interpreter/src/loader/nodes/While.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleGelu.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,19 +14,25 @@
* limitations under the License.
*/
-#include "Builders.h"
+#include "luci/ConnectNode.h"
-#include "kernels/While.h"
-
-namespace luci_interpreter
+namespace
{
-std::unique_ptr<Kernel> build_kernel_CircleWhile(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
+void connect(luci::ConnectNode *cn, const luci::CircleGelu *node)
{
- // TODO: support IF operation
- assert(false && "Not supported now");
+ auto *cloned = loco::must_cast<luci::CircleGelu *>(cn->find_clone(node));
+
+ luci::CircleNode *features = loco::must_cast<luci::CircleNode *>(node->features());
+
+ cloned->features(cn->find_clone(features));
}
-} // namespace luci_interpreter
+} // namespace
+
+namespace luci
+{
+
+void ConnectNode::visit(const luci::CircleGelu *node) { connect(this, node); }
+
+} // namespace luci
diff --git a/compiler/luci/partition/src/Nodes/CircleGelu.test.cpp b/compiler/luci/partition/src/Nodes/CircleGelu.test.cpp
new file mode 100644
index 000000000..ebef3f791
--- /dev/null
+++ b/compiler/luci/partition/src/Nodes/CircleGelu.test.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/ConnectNode.h"
+
+#include "ConnectNode.test.h"
+
+#include <luci/Service/CircleNodeClone.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class NodeGraphlet : public NodeGraphletT<luci::CircleGelu>
+{
+public:
+ NodeGraphlet() = default;
+};
+
+class TestNodeGraph : public TestIOGraph, public NodeGraphlet
+{
+public:
+ TestNodeGraph() = default;
+
+public:
+ void init(const ShapeU32 shape)
+ {
+ TestIOGraph::init(shape, shape);
+ NodeGraphlet::init(g());
+
+ node()->features(input());
+
+ output()->from(node());
+ }
+};
+
+} // namespace
+
+TEST(ConnectNodeTest, connect_Gelu)
+{
+ TestNodeGraph tng;
+ tng.init({2, 3});
+
+ ConnectionTestHelper cth;
+ cth.prepare_inputs(&tng);
+
+ auto *node = tng.node();
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleGelu *>(node));
+
+ auto *clone = luci::clone_node(node, cth.graph_clone());
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleGelu *>(clone));
+
+ cth.clone_connect(node, clone);
+
+ ASSERT_EQ(1, clone->arity());
+ ASSERT_EQ(cth.inputs(0), clone->arg(0));
+}
+
+TEST(ConnectNodeTest, connect_Gelu_NEG)
+{
+ TestNodeGraph tng;
+ tng.init({2, 3});
+
+ ConnectionTestHelper cth;
+ cth.prepare_inputs_miss(&tng);
+
+ auto *node = tng.node();
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleGelu *>(node));
+
+ auto *clone = luci::clone_node(node, cth.graph_clone());
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleGelu *>(clone));
+
+ EXPECT_ANY_THROW(cth.clone_connect(node, clone));
+}
diff --git a/compiler/luci/partition/src/Nodes/CircleHardSwish.cpp b/compiler/luci/partition/src/Nodes/CircleHardSwish.cpp
new file mode 100644
index 000000000..d6903f305
--- /dev/null
+++ b/compiler/luci/partition/src/Nodes/CircleHardSwish.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/ConnectNode.h"
+
+namespace
+{
+
+void connect(luci::ConnectNode *cn, const luci::CircleHardSwish *node)
+{
+ auto *cloned = loco::must_cast<luci::CircleHardSwish *>(cn->find_clone(node));
+
+ luci::CircleNode *features = loco::must_cast<luci::CircleNode *>(node->features());
+
+ cloned->features(cn->find_clone(features));
+}
+
+} // namespace
+
+namespace luci
+{
+
+void ConnectNode::visit(const luci::CircleHardSwish *node) { connect(this, node); }
+
+} // namespace luci
diff --git a/compiler/luci/partition/src/Nodes/CircleHardSwish.test.cpp b/compiler/luci/partition/src/Nodes/CircleHardSwish.test.cpp
new file mode 100644
index 000000000..770597313
--- /dev/null
+++ b/compiler/luci/partition/src/Nodes/CircleHardSwish.test.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/ConnectNode.h"
+
+#include "ConnectNode.test.h"
+
+#include <luci/Service/CircleNodeClone.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class NodeGraphlet : public NodeGraphletT<luci::CircleHardSwish>
+{
+public:
+ NodeGraphlet() = default;
+};
+
+class TestNodeGraph : public TestIOGraph, public NodeGraphlet
+{
+public:
+ TestNodeGraph() = default;
+
+public:
+ void init(const ShapeU32 shape)
+ {
+ TestIOGraph::init(shape, shape);
+ NodeGraphlet::init(g());
+
+ node()->features(input());
+
+ output()->from(node());
+ }
+};
+
+} // namespace
+
+TEST(ConnectNodeTest, connect_HardSwish)
+{
+ TestNodeGraph tng;
+ tng.init({2, 3});
+
+ ConnectionTestHelper cth;
+ cth.prepare_inputs(&tng);
+
+ auto *node = tng.node();
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleHardSwish *>(node));
+
+ auto *clone = luci::clone_node(node, cth.graph_clone());
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleHardSwish *>(clone));
+
+ cth.clone_connect(node, clone);
+
+ ASSERT_EQ(1, clone->arity());
+ ASSERT_EQ(cth.inputs(0), clone->arg(0));
+}
+
+TEST(ConnectNodeTest, connect_HardSwish_NEG)
+{
+ TestNodeGraph tng;
+ tng.init({2, 3});
+
+ ConnectionTestHelper cth;
+ cth.prepare_inputs_miss(&tng);
+
+ auto *node = tng.node();
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleHardSwish *>(node));
+
+ auto *clone = luci::clone_node(node, cth.graph_clone());
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleHardSwish *>(clone));
+
+ EXPECT_ANY_THROW(cth.clone_connect(node, clone));
+}
diff --git a/compiler/luci/partition/src/Nodes/CircleTransposeConv.test.cpp b/compiler/luci/partition/src/Nodes/CircleTransposeConv.test.cpp
index 68adaad81..7dbdfd92f 100644
--- a/compiler/luci/partition/src/Nodes/CircleTransposeConv.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleTransposeConv.test.cpp
@@ -38,6 +38,7 @@ public:
NodeGraphletT<luci::CircleTransposeConv>::init(g);
_node->padding(luci::Padding::VALID);
+ _node->fusedActivationFunction(luci::FusedActFunc::RELU);
}
};
diff --git a/compiler/luci/pass/include/luci/CircleOptimizer.h b/compiler/luci/pass/include/luci/CircleOptimizer.h
index d77e89db1..6ebacee39 100644
--- a/compiler/luci/pass/include/luci/CircleOptimizer.h
+++ b/compiler/luci/pass/include/luci/CircleOptimizer.h
@@ -63,6 +63,7 @@ public:
MakeBatchNormGammaPositive,
FuseActivationFunction,
FusePRelu,
+ FuseGelu,
ShuffleWeightTo16x1Float32,
RemoveRedundantTranspose,
ReplaceMulAddWithDepthwiseConv,
@@ -80,6 +81,7 @@ public:
RemoveUnnecessaryReshape,
TransformMinMaxToRelu6Pass,
TransformMinReluToRelu6Pass,
+ DecomposeHardSwishPass,
SubstituteStridedSliceToReshape,
SubstituteTransposeToReshape,
RemoveRedundantQuantize,
diff --git a/compiler/luci/pass/include/luci/CircleQuantizer.h b/compiler/luci/pass/include/luci/CircleQuantizer.h
index 4e7074d98..463f31790 100644
--- a/compiler/luci/pass/include/luci/CircleQuantizer.h
+++ b/compiler/luci/pass/include/luci/CircleQuantizer.h
@@ -45,6 +45,7 @@ public:
CopyQuantParam,
ForceQuantParam,
ConvertToFakeQuantizedModel,
+ QuantizeWeights,
};
enum AlgorithmParameters
diff --git a/compiler/luci/pass/include/luci/DynamicBatchToSingleBatch.h b/compiler/luci/pass/include/luci/DynamicBatchToSingleBatch.h
new file mode 100644
index 000000000..2a02777f6
--- /dev/null
+++ b/compiler/luci/pass/include/luci/DynamicBatchToSingleBatch.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_DYNAMIC_BATCH_TO_SINGLE_BATCH_H__
+#define __LUCI_DYNAMIC_BATCH_TO_SINGLE_BATCH_H__
+
+#include <luci/IR/Module.h>
+
+namespace luci
+{
+
+void dynamic_batch_to_single_batch(luci::Module *);
+
+} // namespace luci
+
+#endif // __LUCI_DYNAMIC_BATCH_TO_SINGLE_BATCH_H__
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/If.cpp b/compiler/luci/pass/include/luci/Pass/DecomposeHardSwishPass.h
index 1c6f12cce..83c16bcee 100644
--- a/onert-micro/luci-interpreter/src/loader/nodes/If.cpp
+++ b/compiler/luci/pass/include/luci/Pass/DecomposeHardSwishPass.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,19 +14,24 @@
* limitations under the License.
*/
-#include "Builders.h"
+#ifndef __LUCI_DECOMPOSE_HARDSWISH_PASS_H__
+#define __LUCI_DECOMPOSE_HARDSWISH_PASS_H__
-#include "kernels/If.h"
+#include <logo/Pass.h>
-namespace luci_interpreter
+namespace luci
{
-std::unique_ptr<Kernel> build_kernel_CircleIf(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
+/**
+ * @brief Class to decompose HardSwish to Add, Mul and Relu6
+ */
+struct DecomposeHardSwishPass final : public logo::Pass
{
- // TODO: support IF operation
- assert(false && "Not supported now");
-}
+ const char *name(void) const final { return "luci::DecomposeHardSwishPass"; }
+
+ bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
-} // namespace luci_interpreter
+#endif // __LUCI_DECOMPOSE_HARDSWISH_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/DynamicBatchToSingleBatchPass.h b/compiler/luci/pass/include/luci/Pass/DynamicBatchToSingleBatchPass.h
new file mode 100644
index 000000000..b3598c986
--- /dev/null
+++ b/compiler/luci/pass/include/luci/Pass/DynamicBatchToSingleBatchPass.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_DYNAMIC_BATCH_TO_SINGLE_BATCH_PASS_H__
+#define __LUCI_DYNAMIC_BATCH_TO_SINGLE_BATCH_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Pass to convert dynamic batch to single batch
+ */
+class DynamicBatchToSingleBatchPass : public logo::Pass
+{
+public:
+ virtual const char *name(void) const { return "luci::DynamicBatchToSingleBatchPass"; }
+
+public:
+ bool run(loco::Graph *graph);
+};
+
+} // namespace luci
+
+#endif //__LUCI_DYNAMIC_BATCH_TO_SINGLE_BATCH_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/FuseGeluPass.h b/compiler/luci/pass/include/luci/Pass/FuseGeluPass.h
new file mode 100644
index 000000000..5fa23036c
--- /dev/null
+++ b/compiler/luci/pass/include/luci/Pass/FuseGeluPass.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_FUSE_GELU_PASS_H__
+#define __LUCI_FUSE_GELU_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Class to fuse certain pattern of subgraph into CircleGelu
+ *
+ * For detailed subgraph pattern to be fused, please check its implementation.
+ */
+struct FuseGeluPass final : public logo::Pass
+{
+ const char *name(void) const final { return "luci::FuseGeluPass"; }
+
+ bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_FUSE_GELU_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/QuantizeWeightsPass.h b/compiler/luci/pass/include/luci/Pass/QuantizeWeightsPass.h
new file mode 100644
index 000000000..646597312
--- /dev/null
+++ b/compiler/luci/pass/include/luci/Pass/QuantizeWeightsPass.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_QUANTIZE_WEIGHTS_PASS_H__
+#define __LUCI_QUANTIZE_WEIGHTS_PASS_H__
+
+#include <loco.h>
+
+#include <logo/Pass.h>
+
+#include <luci/Pass/QuantizationParameters.h>
+
+namespace luci
+{
+
+/**
+ * @brief Pass to quantize weights
+ */
+class QuantizeWeightsPass : public logo::Pass
+{
+public:
+ struct Context
+ {
+ loco::DataType input_model_dtype = loco::DataType::Unknown;
+ loco::DataType output_model_dtype = loco::DataType::Unknown;
+ QuantizationGranularity granularity = QuantizationGranularity::ChannelWise;
+ };
+
+public:
+ QuantizeWeightsPass(std::unique_ptr<Context> &&ctx) : _ctx{std::move(ctx)}
+ {
+ // DO NOTHING
+ }
+
+public:
+ QuantizeWeightsPass(loco::DataType input_model_dtype, loco::DataType output_model_dtype,
+ QuantizationGranularity granularity)
+ {
+ _ctx = std::make_unique<Context>();
+ {
+ _ctx->input_model_dtype = input_model_dtype;
+ _ctx->output_model_dtype = output_model_dtype;
+ _ctx->granularity = granularity;
+ }
+ }
+ virtual const char *name(void) const { return "luci::QuantizeWeightsPass"; }
+
+public:
+ bool run(loco::Graph *graph);
+
+private:
+ std::unique_ptr<Context> _ctx;
+};
+
+} // namespace luci
+
+#endif //__LUCI_QUANTIZE_WEIGHTS_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/RequantizePass.h b/compiler/luci/pass/include/luci/Pass/RequantizePass.h
index c6c424f1b..50b9073b5 100644
--- a/compiler/luci/pass/include/luci/Pass/RequantizePass.h
+++ b/compiler/luci/pass/include/luci/Pass/RequantizePass.h
@@ -27,7 +27,7 @@ namespace luci
{
/**
- * @brief Pass to quantize weights
+ * @brief Pass to re-quantize graph (ex: int8 -> uint8)
*/
class RequantizePass : public logo::Pass
{
diff --git a/compiler/luci/pass/src/CircleOptimizer.cpp b/compiler/luci/pass/src/CircleOptimizer.cpp
index 5e1613ad9..b011581af 100644
--- a/compiler/luci/pass/src/CircleOptimizer.cpp
+++ b/compiler/luci/pass/src/CircleOptimizer.cpp
@@ -39,6 +39,7 @@
#include "luci/Pass/FuseMeanWithMeanPass.h"
#include "luci/Pass/FusePreActivationBatchNormPass.h"
#include "luci/Pass/FusePReluPass.h"
+#include "luci/Pass/FuseGeluPass.h"
#include "luci/Pass/FuseTransposeWithMeanPass.h"
#include "luci/Pass/MakeBatchNormGammaPositivePass.h"
#include "luci/Pass/RemoveDuplicateConstPass.h"
@@ -70,6 +71,7 @@
#include "luci/Pass/SubstituteTransposeToReshapePass.h"
#include "luci/Pass/TransformMinMaxToRelu6Pass.h"
#include "luci/Pass/TransformMinReluToRelu6Pass.h"
+#include "luci/Pass/DecomposeHardSwishPass.h"
#include "luci/Pass/UnrollUnidirectionalSequenceLSTMPass.h"
// TODO add more passes
@@ -137,7 +139,8 @@ bool OptimizeOptionsImpl::query(Algorithm algo)
}
// TODO Make a struct for args
-void convert_nchw_to_nhwc(loco::Graph *g, bool preserve_input, bool preserve_output, bool fuse_fc)
+void convert_nchw_to_nhwc(loco::Graph *g, bool preserve_input, bool preserve_output, bool fuse_fc,
+ bool fuse_gelu)
{
logo::Phase phase;
@@ -160,6 +163,12 @@ void convert_nchw_to_nhwc(loco::Graph *g, bool preserve_input, bool preserve_out
if (fuse_fc)
phase.emplace_back(std::make_unique<luci::FuseAddWithFullyConnectedPass>());
+ // Fuse decomposed ops to Gelu Op
+ // Why here? ConverNCHWToNHWCPass inserts additional Ops, so it is better to fuse
+ // Gelu in advance.
+ if (fuse_gelu)
+ phase.emplace_back(std::make_unique<luci::FuseGeluPass>());
+
phase.emplace_back(
std::make_unique<luci::ConvertNCHWToNHWCPass>(preserve_input, preserve_output));
@@ -216,8 +225,9 @@ void CircleOptimizer::optimize(loco::Graph *g) const
_options->param(Options::AlgorithmParameters::NCHW_to_NHWC_output_shape) != "true";
bool fuse_fc = _options->query(Options::Algorithm::FuseAddWithFullyConnected);
+ bool fuse_gelu = _options->query(Options::Algorithm::FuseGelu);
- convert_nchw_to_nhwc(g, preserve_input, preserve_output, fuse_fc);
+ convert_nchw_to_nhwc(g, preserve_input, preserve_output, fuse_fc, fuse_gelu);
}
/* TRANSFORM DECLARATION BEGIN */
@@ -283,6 +293,10 @@ void CircleOptimizer::optimize(loco::Graph *g) const
{
phase.emplace_back(std::make_unique<FusePReluPass>());
}
+ if (_options->query(Options::Algorithm::FuseGelu))
+ {
+ phase.emplace_back(std::make_unique<FuseGeluPass>());
+ }
if (_options->query(Options::Algorithm::FuseTransposeWithMean))
{
phase.emplace_back(std::make_unique<FuseTransposeWithMeanPass>());
@@ -319,14 +333,6 @@ void CircleOptimizer::optimize(loco::Graph *g) const
{
phase.emplace_back(std::make_unique<luci::FoldSparseToDensePass>());
}
- if (_options->query(Options::Algorithm::ForwardReshapeToUnaryOp))
- {
- phase.emplace_back(std::make_unique<luci::ForwardReshapeToUnaryOpPass>());
- }
- if (_options->query(Options::Algorithm::ForwardTransposeOp))
- {
- phase.emplace_back(std::make_unique<luci::ForwardTransposeOpPass>());
- }
if (_options->query(Options::Algorithm::FusePreActivationBatchNorm))
{
phase.emplace_back(std::make_unique<luci::FusePreActivationBatchNormPass>());
@@ -428,10 +434,26 @@ void CircleOptimizer::optimize(loco::Graph *g) const
{
phase.emplace_back(std::make_unique<luci::TransformMinReluToRelu6Pass>());
}
+ if (_options->query(Options::Algorithm::DecomposeHardSwishPass))
+ {
+ phase.emplace_back(std::make_unique<luci::DecomposeHardSwishPass>());
+ }
if (_options->query(Options::Algorithm::UnrollUnidirSeqLSTM))
{
phase.emplace_back(std::make_unique<luci::UnrollUnidirectionalSequenceLSTMPass>());
}
+ // Forward Reshape/Transpose is done after
+ // 1. SubstituteXXXToReshape
+ // 2. RemoveRedundantReshape/Transpose
+ // See https://github.com/Samsung/ONE/pull/10596 for more details
+ if (_options->query(Options::Algorithm::ForwardReshapeToUnaryOp))
+ {
+ phase.emplace_back(std::make_unique<luci::ForwardReshapeToUnaryOpPass>());
+ }
+ if (_options->query(Options::Algorithm::ForwardTransposeOp))
+ {
+ phase.emplace_back(std::make_unique<luci::ForwardTransposeOpPass>());
+ }
/* TRANSFORM DECLARATION END */
diff --git a/compiler/luci/pass/src/CircleQuantizer.cpp b/compiler/luci/pass/src/CircleQuantizer.cpp
index 3ffa1180c..9039a839f 100644
--- a/compiler/luci/pass/src/CircleQuantizer.cpp
+++ b/compiler/luci/pass/src/CircleQuantizer.cpp
@@ -26,6 +26,7 @@
#include "luci/Pass/QuantizePreCheckerPass.h"
#include "luci/Pass/QuantizeWithMinMaxPass.h"
#include "luci/Pass/QuantizeDequantizeWeightsPass.h"
+#include "luci/Pass/QuantizeWeightsPass.h"
#include "luci/Pass/CircleShapeInferencePass.h"
#include "luci/Pass/CircleTypeInferencePass.h"
@@ -439,14 +440,14 @@ void CircleQuantizer::quantize(loco::Graph *g) const
throw std::runtime_error("Unsupported granularity. List of supported granularity: " +
to_string(qwmm_supported_granularity));
- for (auto dtype : input_type_vec)
+ for (const auto &dtype : input_type_vec)
{
if (!in_array(to_lower_case(dtype), qwmm_supported_input_type))
throw std::runtime_error("Unsupported input type. List of supported input types: " +
to_string(qwmm_supported_input_type));
}
- for (auto dtype : output_type_vec)
+ for (const auto &dtype : output_type_vec)
{
if (!in_array(to_lower_case(dtype), qwmm_supported_output_type))
throw std::runtime_error("Unsupported output type. List of supported output types: " +
@@ -536,6 +537,40 @@ void CircleQuantizer::quantize(loco::Graph *g) const
verifier.verify(g);
}
+ if (_options->query(Options::Algorithm::QuantizeWeights))
+ {
+ static const std::vector<std::string> qw_supported_input_model_dtype{"float32"};
+ static const std::vector<std::string> qw_supported_output_model_dtype{"int8", "int16"};
+ static const std::vector<std::string> qw_supported_granularity{"channel"};
+
+ auto input_model_dtype =
+ _options->param(Options::AlgorithmParameters::Quantize_input_model_dtype);
+ auto output_model_dtype =
+ _options->param(Options::AlgorithmParameters::Quantize_output_model_dtype);
+ auto granularity = _options->param(Options::AlgorithmParameters::Quantize_granularity);
+
+ if (!in_array(to_lower_case(input_model_dtype), qw_supported_input_model_dtype))
+ throw std::runtime_error("Unsupported input type. List of supported input type: " +
+ to_string(qw_supported_input_model_dtype));
+
+ if (!in_array(to_lower_case(output_model_dtype), qw_supported_output_model_dtype))
+ throw std::runtime_error("Unsupported output type. List of supported output type: " +
+ to_string(qw_supported_output_model_dtype));
+
+ if (!in_array(to_lower_case(granularity), qw_supported_granularity))
+ throw std::runtime_error("Unsupported granularity. List of supported granularity: " +
+ to_string(qw_supported_granularity));
+ auto ctx = std::make_unique<luci::QuantizeWeightsPass::Context>();
+ {
+ ctx->input_model_dtype = str_to_dtype(input_model_dtype);
+ ctx->output_model_dtype = str_to_dtype(output_model_dtype);
+ ctx->granularity = str_to_granularity(granularity);
+ }
+ luci::QuantizeWeightsPass weights_quantizer(std::move(ctx));
+
+ weights_quantizer.run(g);
+ }
+
// Requantize
if (_options->query(Options::Algorithm::Requantize))
{
diff --git a/compiler/luci/pass/src/ConvertNCHWToNHWCPass.cpp b/compiler/luci/pass/src/ConvertNCHWToNHWCPass.cpp
index 99e1e2939..ac4320246 100644
--- a/compiler/luci/pass/src/ConvertNCHWToNHWCPass.cpp
+++ b/compiler/luci/pass/src/ConvertNCHWToNHWCPass.cpp
@@ -55,16 +55,18 @@ bool broadcastable(const luci::CircleConst *from, const luci::CircleNode *to)
return true;
}
-// Expand node to rank 4
+// Return node with rank 4
// node should have rank less than or equal to 4
-void expand_to_rank_4(luci::CircleConst *node)
+// 1 is inserted to the front of shape if rank is less than 4
+// For example, [2] -> [1, 1, 1, 2]
+luci::CircleConst *expand_to_rank_4(luci::CircleConst *node)
{
auto original_rank = node->rank();
assert(original_rank <= 4); // FIX_CALLER_UNLESS
if (original_rank == 4)
- return;
+ return node;
std::vector<uint32_t> original_shape;
for (uint32_t i = 0; i < original_rank; i++)
@@ -72,12 +74,17 @@ void expand_to_rank_4(luci::CircleConst *node)
original_shape.emplace_back(node->dim(i).value());
}
- node->rank(4);
+ auto cloned = luci::clone(node);
+ cloned->name(cloned->name() + "_rank4");
+
+ cloned->rank(4);
for (uint32_t i = 0; i < (4 - original_rank); i++)
- node->dim(i) = 1;
+ cloned->dim(i) = 1;
for (uint32_t i = 0; i < original_rank; i++)
- node->dim(i + (4 - original_rank)) = original_shape.at(i);
+ cloned->dim(i + (4 - original_rank)) = original_shape.at(i);
+
+ return cloned;
}
bool is_output(const loco::Node *node)
@@ -564,7 +571,7 @@ bool is_NCHW_with_const(const luci::CircleMul *node, luci::CircleNode *&pred_nod
if (not broadcastable(multiplier, node))
return false;
- expand_to_rank_4(multiplier);
+ multiplier = expand_to_rank_4(multiplier);
return true;
}
@@ -602,7 +609,7 @@ bool is_NCHW_with_const(const luci::CircleAdd *node, luci::CircleNode *&pred_nod
if (not broadcastable(beta, node))
return false;
- expand_to_rank_4(beta);
+ beta = expand_to_rank_4(beta);
return true;
}
@@ -834,6 +841,8 @@ class ConvertNCHWToNHWC final : public luci::CircleNodeMutableVisitor<bool>
bool visit(luci::CircleElu *node) { return convert_unary_features<luci::CircleElu>(node); }
+ bool visit(luci::CircleGelu *node) { return convert_unary_features<luci::CircleGelu>(node); }
+
bool visit(luci::CircleLeakyRelu *node)
{
return convert_unary_features<luci::CircleLeakyRelu>(node);
@@ -1510,6 +1519,7 @@ bool ConvertNCHWToNHWCPass::run(loco::Graph *g)
case luci::CircleOpcode::ADD:
case luci::CircleOpcode::CONCATENATION:
case luci::CircleOpcode::ELU:
+ case luci::CircleOpcode::GELU:
case luci::CircleOpcode::LEAKY_RELU:
case luci::CircleOpcode::LOGISTIC:
case luci::CircleOpcode::MAXIMUM:
diff --git a/compiler/luci/pass/src/ConvertNCHWToNHWCPass.test.cpp b/compiler/luci/pass/src/ConvertNCHWToNHWCPass.test.cpp
index fd326518e..85648cf2c 100644
--- a/compiler/luci/pass/src/ConvertNCHWToNHWCPass.test.cpp
+++ b/compiler/luci/pass/src/ConvertNCHWToNHWCPass.test.cpp
@@ -535,6 +535,8 @@ public:
luci::CircleMaximum *max = nullptr;
};
+static constexpr std::initializer_list<uint32_t> kDefaultShape = {1, 16, 1, 1};
+
class MeanGraph final : public SimpleGraph
{
protected:
@@ -577,7 +579,7 @@ public:
private:
bool _keep_dims = true;
std::vector<int32_t> _axes = {2, 3};
- std::initializer_list<uint32_t> _shape = {1, 16, 1, 1};
+ std::initializer_list<uint32_t> _shape = kDefaultShape;
};
class MinimumGraph final : public SimpleGraph
@@ -876,7 +878,7 @@ public:
private:
bool _keep_dims = true;
std::vector<int32_t> _axes = {2, 3};
- std::initializer_list<uint32_t> _shape = {1, 16, 1, 1};
+ std::initializer_list<uint32_t> _shape = kDefaultShape;
};
class ReduceMinGraph final : public SimpleGraph
@@ -921,7 +923,7 @@ public:
private:
bool _keep_dims = true;
std::vector<int32_t> _axes = {2, 3};
- std::initializer_list<uint32_t> _shape = {1, 16, 1, 1};
+ std::initializer_list<uint32_t> _shape = kDefaultShape;
};
class ReluGraph final : public SimpleGraph
diff --git a/compiler/luci/pass/src/ConvertToFakeQuantizedModelPass.cpp b/compiler/luci/pass/src/ConvertToFakeQuantizedModelPass.cpp
index aacfce3d0..ae5ab1519 100644
--- a/compiler/luci/pass/src/ConvertToFakeQuantizedModelPass.cpp
+++ b/compiler/luci/pass/src/ConvertToFakeQuantizedModelPass.cpp
@@ -198,6 +198,7 @@ struct FakeQuantize final : public luci::CircleNodeMutableVisitor<void>
void visit(luci::CircleDepthwiseConv2D *node) { fq_activation(node); }
void visit(luci::CircleDiv *node) { fq_activation(node); }
void visit(luci::CircleFullyConnected *node) { fq_activation(node); }
+ void visit(luci::CircleGelu *node) { fq_activation(node); }
void visit(luci::CircleInstanceNorm *node) { fq_activation(node); }
void visit(luci::CircleLeakyRelu *node) { fq_activation(node); }
void visit(luci::CircleLogistic *node) { fq_activation(node); }
@@ -217,6 +218,9 @@ struct FakeQuantize final : public luci::CircleNodeMutableVisitor<void>
void visit(luci::CircleRsqrt *node) { fq_activation(node); }
void visit(luci::CircleSoftmax *node) { fq_activation(node); }
void visit(luci::CircleSqrt *node) { fq_activation(node); }
+ void visit(luci::CircleSquaredDifference *node) { fq_activation(node); }
+ void visit(luci::CircleSub *node) { fq_activation(node); }
+ void visit(luci::CircleSum *node) { fq_activation(node); }
void visit(luci::CircleTanh *node) { fq_activation(node); }
void visit(luci::CircleTransposeConv *node) { fq_activation(node); }
diff --git a/compiler/luci/pass/src/DecomposeHardSwishPass.cpp b/compiler/luci/pass/src/DecomposeHardSwishPass.cpp
new file mode 100644
index 000000000..bd99d2de0
--- /dev/null
+++ b/compiler/luci/pass/src/DecomposeHardSwishPass.cpp
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/DecomposeHardSwishPass.h"
+
+#include "helpers/NodeFiller.h"
+#include "helpers/TypeMapper.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+
+namespace
+{
+/**
+ * BEFORE
+ * [CircleNode]
+ * |
+ * |
+ * [CircleHardSwish]
+ * |
+ * |
+ * [CircleNode]
+ *
+ *
+ * AFTER
+ *
+ * [CircleNode] [CircleConst]
+ * | \ /
+ * | \ /
+ * | [CircleAdd]
+ * | |
+ * | |
+ * \ [CircleRelu6] [CircleConst]
+ * \ \ /
+ * \ \ /
+ * \ [CircleMul]
+ * \ /
+ * \ /
+ * [CircleMul]
+ * |
+ * |
+ * [CircleNode]
+ *
+ */
+bool decompose_hardswish(luci::CircleHardSwish *hardswish)
+{
+ if (not hardswish)
+ return false;
+
+ if (hardswish->dtype() != loco::DataType::FLOAT32)
+ return false;
+
+ auto g = hardswish->graph();
+
+ auto name = hardswish->name();
+ assert(name.length() > 0);
+
+ // Create a const for CircleAdd operation
+ auto add_const = g->nodes()->create<luci::CircleConst>();
+ add_const->shape({}); // scalar
+ add_const->dtype(loco::DataType::FLOAT32);
+ add_const->rank(0);
+ add_const->size<loco::DataType::FLOAT32>(1);
+ add_const->at<loco::DataType::FLOAT32>(0) = 3.;
+ add_const->name(name + "/Add/const");
+ luci::add_origin(add_const, luci::get_origin(hardswish));
+
+ // Create an Add operation
+ auto add = g->nodes()->create<luci::CircleAdd>();
+ add->fusedActivationFunction(luci::FusedActFunc::NONE);
+ add->x(hardswish->features());
+ add->y(add_const);
+ add->name(name + "/Add");
+ luci::add_origin(add, luci::get_origin(hardswish));
+
+ // Create a Relu6 operation
+ auto relu6 = g->nodes()->create<luci::CircleRelu6>();
+ relu6->features(add);
+ relu6->name(name + "/Relu6");
+ luci::add_origin(relu6, luci::get_origin(hardswish));
+
+ // Create a const for CircleMul operation
+ auto mul_const = g->nodes()->create<luci::CircleConst>();
+ mul_const->shape({}); // scalar
+ mul_const->dtype(loco::DataType::FLOAT32);
+ mul_const->rank(0);
+ mul_const->size<loco::DataType::FLOAT32>(1);
+ mul_const->at<loco::DataType::FLOAT32>(0) = 1. / 6.;
+ mul_const->name(name + "/Mul/const");
+ luci::add_origin(mul_const, luci::get_origin(hardswish));
+
+ // Create first Mul operation
+ auto mul1 = g->nodes()->create<luci::CircleMul>();
+ mul1->fusedActivationFunction(luci::FusedActFunc::NONE);
+ mul1->x(relu6);
+ mul1->y(mul_const);
+ mul1->name(name + "/Mul1");
+ luci::add_origin(mul1, luci::get_origin(hardswish));
+
+ // Create second Mul operation
+ auto mul2 = g->nodes()->create<luci::CircleMul>();
+ mul2->fusedActivationFunction(luci::FusedActFunc::NONE);
+ mul2->x(hardswish->features());
+ mul2->y(mul1);
+ mul2->name(name + "/Mul2");
+ luci::add_origin(mul2, luci::get_origin(hardswish));
+
+ replace(hardswish).with(mul2);
+
+ return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+bool DecomposeHardSwishPass::run(loco::Graph *g)
+{
+ bool changed = false;
+
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ if (auto hardswish = dynamic_cast<luci::CircleHardSwish *>(node))
+ {
+ if (decompose_hardswish(hardswish))
+ changed = true;
+ }
+ }
+
+ return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/DecomposeHardSwishPass.test.cpp b/compiler/luci/pass/src/DecomposeHardSwishPass.test.cpp
new file mode 100644
index 000000000..d51a07fdc
--- /dev/null
+++ b/compiler/luci/pass/src/DecomposeHardSwishPass.test.cpp
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/DecomposeHardSwishPass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+/**
+ * HardSwish graph
+ *
+ * [CircleInput]
+ * |
+ * |
+ * [CircleHardSwish]
+ * |
+ * |
+ * [CircleOutput]
+ */
+struct HardSwishGraph
+{
+ loco::Graph _g;
+ luci::CircleInput *_input = nullptr;
+ luci::CircleHardSwish *_hardswish = nullptr;
+ luci::CircleOutput *_output = nullptr;
+};
+
+class DecomposeHardSwishPass : public ::testing::Test
+{
+protected:
+ void MakeGraph()
+ {
+ const int N = 1;
+ const int H = 4;
+ const int W = 4;
+ const int C = 3;
+
+ // graph input and output
+ auto graph_input = _hardswish_g._g.inputs()->create();
+ auto graph_output = _hardswish_g._g.outputs()->create();
+
+ // CircleInput
+ _hardswish_g._input = _hardswish_g._g.nodes()->create<luci::CircleInput>();
+ _hardswish_g._input->index(graph_input->index());
+ _hardswish_g._input->shape({N, H, W, C});
+ _hardswish_g._input->dtype(loco::DataType::FLOAT32);
+ _hardswish_g._input->name("input");
+
+ // CircleHardSwish
+ _hardswish_g._hardswish = _hardswish_g._g.nodes()->create<luci::CircleHardSwish>();
+ _hardswish_g._hardswish->features(_hardswish_g._input);
+ _hardswish_g._hardswish->shape({N, H, W, C});
+ _hardswish_g._hardswish->dtype(loco::DataType::FLOAT32);
+ _hardswish_g._hardswish->name("hardswish");
+
+ // CircleOutput
+ _hardswish_g._output = _hardswish_g._g.nodes()->create<luci::CircleOutput>();
+ _hardswish_g._output->index(graph_output->index());
+ _hardswish_g._output->from(_hardswish_g._hardswish);
+ _hardswish_g._output->shape({N, H, W, C});
+ _hardswish_g._output->dtype(loco::DataType::FLOAT32);
+ _hardswish_g._output->name("output");
+ }
+
+ void MakeInt32Graph()
+ {
+ const int N = 1;
+ const int H = 4;
+ const int W = 4;
+ const int C = 3;
+
+ // graph input and output
+ auto graph_input = _hardswish_int32_g._g.inputs()->create();
+ auto graph_output = _hardswish_int32_g._g.outputs()->create();
+
+ // CircleInput
+ _hardswish_int32_g._input = _hardswish_int32_g._g.nodes()->create<luci::CircleInput>();
+ _hardswish_int32_g._input->index(graph_input->index());
+ _hardswish_int32_g._input->shape({N, H, W, C});
+ _hardswish_int32_g._input->dtype(loco::DataType::S32);
+ _hardswish_int32_g._input->name("input");
+
+ // CircleHardSwish
+ _hardswish_int32_g._hardswish = _hardswish_int32_g._g.nodes()->create<luci::CircleHardSwish>();
+ _hardswish_int32_g._hardswish->features(_hardswish_int32_g._input);
+ _hardswish_int32_g._hardswish->shape({N, H, W, C});
+ _hardswish_int32_g._hardswish->dtype(loco::DataType::S32);
+ _hardswish_int32_g._hardswish->name("hardswish");
+
+ // CircleOutput
+ _hardswish_int32_g._output = _hardswish_int32_g._g.nodes()->create<luci::CircleOutput>();
+ _hardswish_int32_g._output->index(graph_output->index());
+ _hardswish_int32_g._output->from(_hardswish_int32_g._hardswish);
+ _hardswish_int32_g._output->shape({N, H, W, C});
+ _hardswish_int32_g._output->dtype(loco::DataType::S32);
+ _hardswish_int32_g._output->name("output");
+ }
+
+ virtual void SetUp()
+ {
+ MakeGraph();
+ MakeInt32Graph();
+ }
+
+protected:
+ luci::DecomposeHardSwishPass _pass;
+ HardSwishGraph _hardswish_g;
+ HardSwishGraph _hardswish_int32_g;
+};
+
+} // namespace
+
+TEST_F(DecomposeHardSwishPass, name)
+{
+ auto const name = _pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+/**
+ * Decomposed graph looks like below.
+ *
+ * [CircleInput] [CircleConst]
+ * | \ /
+ * | \ /
+ * | [CircleAdd]
+ * | |
+ * | |
+ * \ [CircleRelu6] [CircleConst]
+ * \ \ /
+ * \ \ /
+ * \ [CircleMul]
+ * \ /
+ * \ /
+ * [CircleMul]
+ * |
+ * |
+ * [CircleOutput]
+ *
+ */
+TEST_F(DecomposeHardSwishPass, simple_test)
+{
+ auto ret = _pass.run(&_hardswish_g._g);
+ EXPECT_TRUE(ret);
+
+ auto mul2 = dynamic_cast<luci::CircleMul *>(_hardswish_g._output->from());
+ EXPECT_NE(nullptr, mul2);
+
+ auto input2 = dynamic_cast<luci::CircleInput *>(mul2->x());
+ EXPECT_NE(nullptr, input2);
+
+ auto mul1 = dynamic_cast<luci::CircleMul *>(mul2->y());
+ EXPECT_NE(nullptr, mul1);
+
+ auto relu6 = dynamic_cast<luci::CircleRelu6 *>(mul1->x());
+ EXPECT_NE(nullptr, relu6);
+
+ auto mul_const = dynamic_cast<luci::CircleConst *>(mul1->y());
+ EXPECT_NE(nullptr, mul_const);
+ EXPECT_FLOAT_EQ(1. / 6., mul_const->at<loco::DataType::FLOAT32>(0));
+
+ auto add = dynamic_cast<luci::CircleAdd *>(relu6->features());
+ EXPECT_NE(nullptr, add);
+
+ auto input1 = dynamic_cast<luci::CircleInput *>(add->x());
+ EXPECT_NE(nullptr, input1);
+
+ auto add_const = dynamic_cast<luci::CircleConst *>(add->y());
+ EXPECT_NE(nullptr, add_const);
+ EXPECT_FLOAT_EQ(3., add_const->at<loco::DataType::FLOAT32>(0));
+}
+
+TEST_F(DecomposeHardSwishPass, check_last_node)
+{
+ auto ret = _pass.run(&_hardswish_g._g);
+ EXPECT_TRUE(ret);
+
+ auto hardswish = dynamic_cast<luci::CircleHardSwish *>(_hardswish_g._output->from());
+ EXPECT_EQ(nullptr, hardswish);
+}
+
+TEST_F(DecomposeHardSwishPass, wrong_condition_NEG)
+{
+ auto ret = _pass.run(&_hardswish_int32_g._g);
+ EXPECT_FALSE(ret);
+
+ auto hardswish = dynamic_cast<luci::CircleHardSwish *>(_hardswish_g._output->from());
+ EXPECT_NE(nullptr, hardswish);
+}
diff --git a/compiler/luci/pass/src/DynamicBatchToSingleBatch.cpp b/compiler/luci/pass/src/DynamicBatchToSingleBatch.cpp
new file mode 100644
index 000000000..86876063a
--- /dev/null
+++ b/compiler/luci/pass/src/DynamicBatchToSingleBatch.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/DynamicBatchToSingleBatch.h"
+
+#include "luci/Pass/DynamicBatchToSingleBatchPass.h"
+#include "luci/Pass/CircleShapeInferencePass.h"
+
+#include "ProgressReporter.h"
+
+#include <logo/Phase.h>
+
+namespace luci
+{
+
+void dynamic_batch_to_single_batch(luci::Module *m)
+{
+ assert(m); // FIX CALLER UNLESS
+
+ for (uint32_t i = 0; i < m->size(); i++)
+ {
+ auto g = m->graph(i);
+
+ logo::Phase phase;
+
+ phase.emplace_back(std::make_unique<luci::DynamicBatchToSingleBatchPass>());
+
+ // Needed to infer shapes of other nodes
+ phase.emplace_back(std::make_unique<luci::CircleShapeInferencePass>());
+
+ ProgressReporter prog(g, logo::PhaseStrategy::Saturate);
+ logo::PhaseRunner<logo::PhaseStrategy::Saturate> phase_runner{g};
+ phase_runner.attach(&prog);
+ phase_runner.run(phase);
+ }
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/DynamicBatchToSingleBatchPass.cpp b/compiler/luci/pass/src/DynamicBatchToSingleBatchPass.cpp
new file mode 100644
index 000000000..59a9f5ab3
--- /dev/null
+++ b/compiler/luci/pass/src/DynamicBatchToSingleBatchPass.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/DynamicBatchToSingleBatchPass.h"
+
+#include <luci/IR/CircleNode.h>
+#include <loco.h>
+
+namespace luci
+{
+
+bool DynamicBatchToSingleBatchPass::run(loco::Graph *g)
+{
+ assert(g); // FIX CALLER UNLESS
+
+ bool changed = false;
+
+ auto graph_inputs = g->inputs();
+
+ // Assume the first dimension is batch dimension
+ const uint32_t BATCH_DIM = 0;
+
+ for (auto node : loco::input_nodes(g))
+ {
+ auto input_node = loco::must_cast<luci::CircleInput *>(node);
+
+ if (input_node->rank() == 0)
+ continue;
+
+ // Skip if batch dimension is known
+ if (input_node->dim(BATCH_DIM).known())
+ continue;
+
+ if (input_node->rank() != 4)
+ {
+ // Limit use only for rank 4 inputs (for NHWC and NCHW)
+ // TODO Enable this if necessary
+ throw std::runtime_error("First dimension of input is unknown, but its rank is not 4.");
+ }
+
+ // 'set' will make the dimension known
+ input_node->dim(BATCH_DIM).set(1);
+
+ // Update graph input
+ auto graph_input = graph_inputs->at(input_node->index());
+ auto graph_input_shape = graph_input->shape();
+ auto tensor_shape = std::make_unique<loco::TensorShape>();
+ {
+ tensor_shape->rank(graph_input_shape->rank());
+ for (uint32_t i = 0; i < tensor_shape->rank(); i++)
+ {
+ tensor_shape->dim(i) = graph_input_shape->dim(i);
+ }
+ tensor_shape->dim(BATCH_DIM).set(1);
+ }
+
+ graph_input->shape(std::move(tensor_shape));
+
+ changed = true;
+ }
+
+ return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/DynamicBatchToSingleBatchPass.test.cpp b/compiler/luci/pass/src/DynamicBatchToSingleBatchPass.test.cpp
new file mode 100644
index 000000000..f19f57d17
--- /dev/null
+++ b/compiler/luci/pass/src/DynamicBatchToSingleBatchPass.test.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/DynamicBatchToSingleBatchPass.h"
+
+#include <loco.h>
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+std::unique_ptr<loco::TensorShape> make_tshape(std::initializer_list<uint32_t> dims)
+{
+ auto tensor_shape = std::make_unique<loco::TensorShape>();
+ {
+ tensor_shape->rank(dims.size());
+ uint32_t axis = 0;
+ for (auto it = dims.begin(); it != dims.end(); ++it)
+ {
+ tensor_shape->dim(axis++) = *it;
+ }
+ }
+
+ return std::move(tensor_shape);
+}
+
+} // namespace
+
+TEST(DynamicBatchToSingleBatchPassTest, simple)
+{
+ luci::DynamicBatchToSingleBatchPass pass;
+
+ auto g = loco::make_graph();
+
+ auto graph_input = g->inputs()->create();
+ {
+ auto tensor_shape = make_tshape({1, 5, 5, 3});
+ tensor_shape->dim(0).unset();
+ graph_input->shape(std::move(tensor_shape));
+ }
+
+ // Create nodes to make relu traversed first
+ auto input = g->nodes()->create<luci::CircleInput>();
+ {
+ input->index(0);
+ input->shape({1, 5, 5, 3});
+ input->dim(0).unset();
+ }
+
+ EXPECT_FALSE(graph_input->shape()->dim(0).known());
+ EXPECT_FALSE(input->dim(0).known());
+
+ EXPECT_TRUE(pass.run(g.get()));
+
+ // Check input is knwon
+ EXPECT_TRUE(graph_input->shape()->dim(0).known());
+ EXPECT_EQ(1, graph_input->shape()->dim(0));
+ EXPECT_TRUE(input->dim(0).known());
+ EXPECT_EQ(1, input->dim(0));
+}
+
+TEST(DynamicBatchToSingleBatchPassTest, simple_NEG)
+{
+ luci::DynamicBatchToSingleBatchPass pass;
+
+ auto g = loco::make_graph();
+
+ auto graph_input = g->inputs()->create();
+ {
+ graph_input->shape({1, 5, 5, 3});
+ }
+
+ // Create nodes to make relu traversed first
+ auto input = g->nodes()->create<luci::CircleInput>();
+ {
+ input->index(0);
+ input->shape({1, 5, 5, 3});
+ }
+
+ EXPECT_FALSE(pass.run(g.get()));
+}
+
+// Remove this test if we support rank 1 in this pass
+TEST(DynamicBatchToSingleBatchPassTest, rank1_NEG)
+{
+ luci::DynamicBatchToSingleBatchPass pass;
+
+ auto g = loco::make_graph();
+
+ auto graph_input = g->inputs()->create();
+ {
+ auto tensor_shape = make_tshape({1});
+ tensor_shape->dim(0).unset();
+ graph_input->shape(std::move(tensor_shape));
+ }
+
+ // Create nodes to make relu traversed first
+ auto input = g->nodes()->create<luci::CircleInput>();
+ {
+ input->index(0);
+ input->shape({1});
+ input->dim(0).unset();
+ }
+
+ EXPECT_FALSE(graph_input->shape()->dim(0).known());
+ EXPECT_FALSE(input->dim(0).known());
+
+ // Rank 1 is unsupported for now
+ EXPECT_ANY_THROW(pass.run(g.get()));
+}
diff --git a/compiler/luci/pass/src/FoldAddV2Pass.test.cpp b/compiler/luci/pass/src/FoldAddV2Pass.test.cpp
index 438d7f077..200fcc093 100644
--- a/compiler/luci/pass/src/FoldAddV2Pass.test.cpp
+++ b/compiler/luci/pass/src/FoldAddV2Pass.test.cpp
@@ -44,10 +44,10 @@ template <loco::DataType T> class FoldAddV2Test : public luci::ConstantFoldingAd
public:
FoldAddV2Test(std::initializer_list<uint32_t> shape) : luci::ConstantFoldingAddTestGraph(shape, T)
{
- _addV2 = _g.nodes()->create<luci::CircleCustom>(2, 1);
- _x = _g.nodes()->create<luci::CircleConst>();
- _y = _g.nodes()->create<luci::CircleConst>();
- _addV2_out = _g.nodes()->create<luci::CircleCustomOut>();
+ _addV2 = _g.nodes()->template create<luci::CircleCustom>(2, 1);
+ _x = _g.nodes()->template create<luci::CircleConst>();
+ _y = _g.nodes()->template create<luci::CircleConst>();
+ _addV2_out = _g.nodes()->template create<luci::CircleCustomOut>();
_addV2->dtype(T);
_x->dtype(T);
diff --git a/compiler/luci/pass/src/FoldCastPass.test.cpp b/compiler/luci/pass/src/FoldCastPass.test.cpp
index 5911adf11..da33e4379 100644
--- a/compiler/luci/pass/src/FoldCastPass.test.cpp
+++ b/compiler/luci/pass/src/FoldCastPass.test.cpp
@@ -31,8 +31,8 @@ public:
FoldCastTest(std::initializer_list<uint32_t> shape)
: luci::ConstantFoldingAddTestGraph(shape, ToT)
{
- _cast = _g.nodes()->create<luci::CircleCast>();
- _x = _g.nodes()->create<luci::CircleConst>();
+ _cast = _g.nodes()->template create<luci::CircleCast>();
+ _x = _g.nodes()->template create<luci::CircleConst>();
_cast->dtype(ToT);
_x->dtype(FromT);
diff --git a/compiler/luci/pass/src/FoldDequantizePass.test.cpp b/compiler/luci/pass/src/FoldDequantizePass.test.cpp
index fb5b6adc0..87dff5dc0 100644
--- a/compiler/luci/pass/src/FoldDequantizePass.test.cpp
+++ b/compiler/luci/pass/src/FoldDequantizePass.test.cpp
@@ -32,8 +32,8 @@ public:
loco::Node *createFoldedPattern() override
{
- _dequantize = _g.nodes()->create<luci::CircleDequantize>();
- _input = _g.nodes()->create<luci::CircleConst>();
+ _dequantize = _g.nodes()->template create<luci::CircleDequantize>();
+ _input = _g.nodes()->template create<luci::CircleConst>();
_dequantize->dtype(loco::DataType::FLOAT32);
_input->dtype(DT);
diff --git a/compiler/luci/pass/src/FuseActivationFunctionPass.cpp b/compiler/luci/pass/src/FuseActivationFunctionPass.cpp
index d83973cd5..868ccd140 100644
--- a/compiler/luci/pass/src/FuseActivationFunctionPass.cpp
+++ b/compiler/luci/pass/src/FuseActivationFunctionPass.cpp
@@ -42,6 +42,11 @@ bool fuse_activation_function(luci::CircleNode *node)
// This will skip fuse for concat as luci-interpreter doesn't support this yet
if (dynamic_cast<luci::CircleConcatenation *>(pred_node) != nullptr)
return false;
+ // TODO remove this work-around
+ // This will skip fuse for TransposeConv as backends does not support this yet
+ // NOTE remove this when XpSepActFromTransposeConvOpPass is removed
+ if (dynamic_cast<luci::CircleTransposeConv *>(pred_node) != nullptr)
+ return false;
auto fused_act = node_with_fused_act->fusedActivationFunction();
diff --git a/compiler/luci/pass/src/FuseAddWithFullyConnectedPass.test.cpp b/compiler/luci/pass/src/FuseAddWithFullyConnectedPass.test.cpp
index 300796594..b132c6bd9 100644
--- a/compiler/luci/pass/src/FuseAddWithFullyConnectedPass.test.cpp
+++ b/compiler/luci/pass/src/FuseAddWithFullyConnectedPass.test.cpp
@@ -16,6 +16,8 @@
#include "luci/Pass/FuseAddWithFullyConnectedPass.h"
+#include "helpers/CreateCircleConst.h"
+
#include <luci/IR/CircleNodes.h>
#include <luci/test/TestIOGraph.h>
@@ -27,52 +29,6 @@ namespace
using namespace luci::test;
-// TODO Reduce duplicate codes in ResolveCustomOpMatMulPass.cpp
-template <typename T>
-luci::CircleConst *create_const_node(loco::Graph *g, const loco::DataType dtype,
- const std::vector<uint32_t> &shape,
- const std::vector<T> &values)
-{
- auto node = g->nodes()->create<luci::CircleConst>();
- node->dtype(dtype);
- node->rank(shape.size());
-
- uint32_t size = 1;
- for (uint32_t i = 0; i < shape.size(); ++i)
- {
- node->dim(i) = shape.at(i);
- size *= shape.at(i);
- }
- node->shape_status(luci::ShapeStatus::VALID);
-
-#define INIT_VALUES(DT) \
- { \
- node->size<DT>(size); \
- for (uint32_t i = 0; i < values.size(); ++i) \
- node->at<DT>(i) = values[i]; \
- }
-
- switch (dtype)
- {
- case loco::DataType::U8:
- INIT_VALUES(loco::DataType::U8);
- break;
- case loco::DataType::S16:
- INIT_VALUES(loco::DataType::S16);
- break;
- case loco::DataType::S32:
- INIT_VALUES(loco::DataType::S32);
- break;
- case loco::DataType::FLOAT32:
- INIT_VALUES(loco::DataType::FLOAT32)
- break;
- default:
- INTERNAL_EXN("create_const_node called with unsupported type");
- break;
- }
- return node;
-}
-
/**
* Simple graph for test
*
@@ -95,10 +51,10 @@ public:
void init(loco::Graph *g)
{
std::vector<float> weights_val(16 * 4);
- _fc_f = create_const_node(g, loco::DataType::FLOAT32, {16, 4}, weights_val);
+ _fc_f = luci::create_const_node(g, loco::DataType::FLOAT32, {16, 4}, weights_val);
std::vector<float> bias_val(16);
- _fc_b = create_const_node(g, loco::DataType::FLOAT32, {1, 16}, bias_val);
+ _fc_b = luci::create_const_node(g, loco::DataType::FLOAT32, {1, 16}, bias_val);
_fc = g->nodes()->create<luci::CircleFullyConnected>();
_fc->weights(_fc_f);
@@ -111,7 +67,7 @@ public:
std::vector<float> addition_val;
for (uint32_t i = 0; i < 16; i++)
addition_val.push_back(static_cast<float>(i));
- _add_c = create_const_node(g, loco::DataType::FLOAT32, {1, 16}, addition_val);
+ _add_c = luci::create_const_node(g, loco::DataType::FLOAT32, {1, 16}, addition_val);
_add = g->nodes()->create<luci::CircleAdd>();
_add->x(_fc);
diff --git a/compiler/luci/pass/src/FuseAddWithTConvPass.cpp b/compiler/luci/pass/src/FuseAddWithTConvPass.cpp
index 852bc8b63..d8e9f11f5 100644
--- a/compiler/luci/pass/src/FuseAddWithTConvPass.cpp
+++ b/compiler/luci/pass/src/FuseAddWithTConvPass.cpp
@@ -44,6 +44,9 @@ namespace
*/
bool fuse_add_with_tconv(luci::CircleTransposeConv *tconv)
{
+ // skip if tconv has fused activation
+ if (tconv->fusedActivationFunction() != luci::FusedActFunc::NONE)
+ return false;
// check whether it has bias or not. This optimization works only if it doesn't.
auto bias = dynamic_cast<luci::CircleOutputExclude *>(tconv->bias());
if (not bias)
diff --git a/compiler/luci/pass/src/FuseBatchNormWithTConvPass.cpp b/compiler/luci/pass/src/FuseBatchNormWithTConvPass.cpp
index 265a8398b..919ce6edc 100644
--- a/compiler/luci/pass/src/FuseBatchNormWithTConvPass.cpp
+++ b/compiler/luci/pass/src/FuseBatchNormWithTConvPass.cpp
@@ -87,6 +87,9 @@ bool fused_batch_norm_with_tconv(luci::CircleAdd *add)
return false;
if (not luci::fill(&scale, &tconv).with_commutative_args_of(mul))
return false;
+ // skip if tconv has fused activation
+ if (tconv->fusedActivationFunction() != luci::FusedActFunc::NONE)
+ return false;
// check scale and shift constant attributes
// TODO maybe rank check is not needed
@@ -215,6 +218,9 @@ bool fused_batch_norm_with_tconv(luci::CircleAdd *add)
fused_tconv->stride()->h(tconv->stride()->h());
fused_tconv->stride()->w(tconv->stride()->w());
fused_tconv->name(name + "/TransposeConv");
+ // TODO set activation from Add and remove adding following Relu/Relu6 Op
+ // when all of our backends supports fused activation of TransposeConv
+ fused_tconv->fusedActivationFunction(luci::FusedActFunc::NONE);
luci::add_origin(fused_tconv,
luci::composite_origin(
{luci::get_origin(add), luci::get_origin(mul), luci::get_origin(tconv)}));
diff --git a/compiler/luci/pass/src/FuseGeluPass.cpp b/compiler/luci/pass/src/FuseGeluPass.cpp
new file mode 100644
index 000000000..e3e7cecb3
--- /dev/null
+++ b/compiler/luci/pass/src/FuseGeluPass.cpp
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/FuseGeluPass.h"
+#include "helpers/NodeFiller.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <luci/Profile/CircleNodeOrigin.h>
+#include <luci/Service/CircleNodeClone.h>
+
+#include <cmath>
+
+#include <cassert>
+
+// Helper to fuse Gelu
+namespace
+{
+
+// Float comparison
+bool same(float a, float b) { return fabs(a - b) < 1e-5; }
+
+class GeluPatternBase
+{
+public:
+ GeluPatternBase(luci::CircleMul *candidate) { _pattern_last_node = candidate; }
+
+ virtual ~GeluPatternBase() = default;
+
+public:
+ virtual bool matched() = 0;
+
+public:
+ luci::CircleNode *_ifm = nullptr;
+ luci::CircleMul *_mul_sqrt = nullptr;
+ luci::CircleCustom *_erf = nullptr;
+ luci::CircleCustomOut *_erf_out = nullptr;
+ luci::CircleAdd *_add_one = nullptr;
+ luci::CircleMul *_mul = nullptr;
+ luci::CircleMul *_mul_half = nullptr;
+ luci::CircleConst *_const_sqrt = nullptr;
+ luci::CircleConst *_const_one = nullptr;
+ luci::CircleConst *_const_half = nullptr;
+ luci::CircleMul *_pattern_last_node = nullptr;
+};
+
+/**
+ * Below diagram shows Gelu pattern to fuse.
+ * - Gelu(x) = 0.5 * x * (1.0 + erf(x / sqrt(2.0)))
+ * - the below pattern will be replaced with one Gelu
+ *
+ * [In]
+ * |
+ * V
+ * +---- ifm
+ * | |
+ * | V
+ * | mul_sqrt (1/sqrt(2) = 0.707106..)
+ * | |
+ * | V
+ * | erf
+ * | |
+ * | V
+ * | add_one (1.0)
+ * | |
+ * | V
+ * +---> mul
+ * |
+ * V
+ * mul_half (0.5)
+ * |
+ * V
+ * [Out]
+ *
+ */
+class GeluPattern1 final : public GeluPatternBase
+{
+public:
+ GeluPattern1(luci::CircleMul *candidate) : GeluPatternBase(candidate)
+ {
+ assert(candidate);
+ _mul_half = candidate;
+ }
+
+public:
+ bool matched() override;
+};
+
+/**
+ * Below diagram shows Gelu pattern to fuse.
+ * - Gelu(x) = 0.5 * x * (1.0 + erf(x / sqrt(2.0)))
+ * - the below pattern will be replaced with one Gelu
+ *
+ * [In]
+ * |
+ * V
+ * +----------- ifm
+ * | |
+ * | V
+ * | mul_sqrt (1/sqrt(2) = 0.707106..)
+ * | |
+ * | V
+ * | erf
+ * mul_half (0.5) |
+ * | V
+ * | add_one (1.0)
+ * | |
+ * | V
+ * +----------> mul
+ * |
+ * |
+ * V
+ * [Out]
+ *
+ */
+class GeluPattern2 final : public GeluPatternBase
+{
+public:
+ GeluPattern2(luci::CircleMul *candidate) : GeluPatternBase(candidate)
+ {
+ assert(candidate);
+ _mul = candidate;
+ }
+
+ ~GeluPattern2() override = default;
+
+public:
+ bool matched() override;
+};
+
+#define CHECK_OR_FALSE(condition) \
+ if (not(condition)) \
+ return false;
+
+bool GeluPattern1::matched()
+{
+ // check pattern
+ CHECK_OR_FALSE(luci::fill(&_mul, &_const_half).with_commutative_args_of(_mul_half));
+ CHECK_OR_FALSE(luci::fill(&_ifm, &_add_one).with_commutative_args_of(_mul));
+ CHECK_OR_FALSE(luci::fill(&_erf_out, &_const_one).with_commutative_args_of(_add_one));
+
+ if (auto erf = dynamic_cast<luci::CircleCustom *>(_erf_out->input()))
+ _erf = erf;
+
+ CHECK_OR_FALSE(_erf != nullptr);
+
+ // Check erf
+ CHECK_OR_FALSE(_erf->custom_code() == "Erf");
+ CHECK_OR_FALSE(_erf->numInputs() == 1);
+ CHECK_OR_FALSE(_erf->numOutputs() == 1);
+
+ if (auto mul_sqrt = dynamic_cast<luci::CircleMul *>(_erf->inputs(0)))
+ _mul_sqrt = mul_sqrt;
+
+ CHECK_OR_FALSE(_mul_sqrt != nullptr);
+
+ CHECK_OR_FALSE(luci::fill(&_ifm, &_const_sqrt).with_commutative_args_of(_mul_sqrt));
+
+ CHECK_OR_FALSE(_mul_sqrt->x() == _ifm);
+ CHECK_OR_FALSE(_mul->x() == _ifm);
+
+ // Check Activation to be NONE
+ CHECK_OR_FALSE(_mul_sqrt->fusedActivationFunction() == luci::FusedActFunc::NONE);
+ CHECK_OR_FALSE(_add_one->fusedActivationFunction() == luci::FusedActFunc::NONE);
+ CHECK_OR_FALSE(_mul->fusedActivationFunction() == luci::FusedActFunc::NONE);
+ CHECK_OR_FALSE(_mul_half->fusedActivationFunction() == luci::FusedActFunc::NONE);
+
+ // check _const_sqrt condition
+ CHECK_OR_FALSE(_const_sqrt->dtype() == loco::DataType::FLOAT32);
+ CHECK_OR_FALSE(_const_sqrt->size<loco::DataType::FLOAT32>() == 1);
+ CHECK_OR_FALSE(::same(_const_sqrt->at<loco::DataType::FLOAT32>(0), sqrtf(0.5f)));
+
+ // check if _const_half is 0.5 (fp32)
+ CHECK_OR_FALSE(_const_half->dtype() == loco::DataType::FLOAT32);
+ CHECK_OR_FALSE(_const_half->size<loco::DataType::FLOAT32>() == 1);
+ CHECK_OR_FALSE(_const_half->at<loco::DataType::FLOAT32>(0) == 0.5);
+
+ // check _const_one condition
+ CHECK_OR_FALSE(_const_one->dtype() == loco::DataType::FLOAT32);
+ CHECK_OR_FALSE(_const_one->size<loco::DataType::FLOAT32>() == 1);
+ CHECK_OR_FALSE(_const_one->at<loco::DataType::FLOAT32>(0) == 1);
+
+ return true;
+}
+
+bool GeluPattern2::matched()
+{
+ // check pattern
+ CHECK_OR_FALSE(luci::fill(&_mul_half, &_add_one).with_commutative_args_of(_mul));
+ CHECK_OR_FALSE(luci::fill(&_ifm, &_const_half).with_commutative_args_of(_mul_half));
+ CHECK_OR_FALSE(luci::fill(&_erf_out, &_const_one).with_commutative_args_of(_add_one));
+
+ CHECK_OR_FALSE(_mul_half->x() == _ifm);
+
+ if (auto erf = dynamic_cast<luci::CircleCustom *>(_erf_out->input()))
+ _erf = erf;
+
+ CHECK_OR_FALSE(_erf != nullptr);
+
+ // Check erf
+ CHECK_OR_FALSE(_erf->custom_code() == "Erf");
+ CHECK_OR_FALSE(_erf->numInputs() == 1);
+ CHECK_OR_FALSE(_erf->numOutputs() == 1);
+
+ if (auto mul_sqrt = dynamic_cast<luci::CircleMul *>(_erf->inputs(0)))
+ _mul_sqrt = mul_sqrt;
+
+ CHECK_OR_FALSE(_mul_sqrt != nullptr);
+
+ CHECK_OR_FALSE(luci::fill(&_ifm, &_const_sqrt).with_commutative_args_of(_mul_sqrt));
+
+ CHECK_OR_FALSE(_mul_sqrt->x() == _ifm);
+
+ // Check Activation to be NONE
+ CHECK_OR_FALSE(_mul_sqrt->fusedActivationFunction() == luci::FusedActFunc::NONE);
+ CHECK_OR_FALSE(_add_one->fusedActivationFunction() == luci::FusedActFunc::NONE);
+ CHECK_OR_FALSE(_mul->fusedActivationFunction() == luci::FusedActFunc::NONE);
+ CHECK_OR_FALSE(_mul_half->fusedActivationFunction() == luci::FusedActFunc::NONE);
+
+ // check _const_sqrt condition
+ CHECK_OR_FALSE(_const_sqrt->dtype() == loco::DataType::FLOAT32);
+ CHECK_OR_FALSE(_const_sqrt->size<loco::DataType::FLOAT32>() == 1);
+ CHECK_OR_FALSE(::same(_const_sqrt->at<loco::DataType::FLOAT32>(0), sqrtf(0.5f)));
+
+ // check if _const_half is 0.5 (fp32)
+ CHECK_OR_FALSE(_const_half->dtype() == loco::DataType::FLOAT32);
+ CHECK_OR_FALSE(_const_half->size<loco::DataType::FLOAT32>() == 1);
+ CHECK_OR_FALSE(_const_half->at<loco::DataType::FLOAT32>(0) == 0.5);
+
+ // check _const_one condition
+ CHECK_OR_FALSE(_const_one->dtype() == loco::DataType::FLOAT32);
+ CHECK_OR_FALSE(_const_one->size<loco::DataType::FLOAT32>() == 1);
+ CHECK_OR_FALSE(_const_one->at<loco::DataType::FLOAT32>(0) == 1);
+
+ return true;
+}
+
+#undef CHECK_OR_FALSE
+
+class FuseGelu final
+{
+public:
+ FuseGelu(const GeluPatternBase *p) : _p(p) {}
+
+public:
+ void apply(void);
+
+private:
+ luci::CircleGelu *create_gelu(loco::Graph *graph);
+
+private:
+ const GeluPatternBase *_p;
+};
+
+luci::CircleGelu *FuseGelu::create_gelu(loco::Graph *graph)
+{
+ assert(graph);
+
+ auto gelu = graph->nodes()->create<luci::CircleGelu>();
+ gelu->features(_p->_ifm);
+ // TODO Support approximate = True pattern
+ gelu->approximate(false);
+ gelu->name(_p->_pattern_last_node->name() + "_gelu");
+ return gelu;
+}
+
+void FuseGelu::apply()
+{
+ auto graph = _p->_pattern_last_node->graph();
+
+ auto gelu = create_gelu(graph);
+
+ // set origin
+ std::vector<std::shared_ptr<luci::CircleNodeOrigin>> origin_vec{
+ luci::get_origin(_p->_mul_sqrt), luci::get_origin(_p->_erf), luci::get_origin(_p->_add_one),
+ luci::get_origin(_p->_mul), luci::get_origin(_p->_mul_half)};
+
+ luci::add_origin(gelu, luci::composite_origin(origin_vec));
+
+ replace(_p->_pattern_last_node).with(gelu);
+}
+
+} // namespace
+
+namespace
+{
+
+bool fuse_gelu(luci::CircleMul *mul)
+{
+ assert(mul);
+
+ // check first pattern
+ GeluPattern1 pattern(mul);
+ if (pattern.matched())
+ {
+ FuseGelu fuse(&pattern);
+ fuse.apply();
+ return true;
+ }
+
+ // check second pattern
+ GeluPattern2 pattern2(mul);
+ if (pattern2.matched())
+ {
+ FuseGelu fuse(&pattern2);
+ fuse.apply();
+ return true;
+ }
+ return false;
+}
+
+} // namespace
+
+namespace luci
+{
+
+bool FuseGeluPass::run(loco::Graph *g)
+{
+ bool changed = false;
+
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ auto mul = dynamic_cast<luci::CircleMul *>(node);
+ if (not mul)
+ continue;
+
+ if (fuse_gelu(mul))
+ changed = true;
+ }
+
+ return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/FuseGeluPass.test.cpp b/compiler/luci/pass/src/FuseGeluPass.test.cpp
new file mode 100644
index 000000000..db6f6993a
--- /dev/null
+++ b/compiler/luci/pass/src/FuseGeluPass.test.cpp
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/FuseGeluPass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <luci/test/TestIOGraph.h>
+
+#include <cmath>
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class GeluGraphlet
+{
+public:
+ GeluGraphlet() = default;
+
+ void init(loco::Graph *g)
+ {
+ _ifm = g->nodes()->create<luci::CircleAbs>();
+ _mul_sqrt = g->nodes()->create<luci::CircleMul>();
+ _erf = g->nodes()->create<luci::CircleCustom>(1, 1);
+ _erf_out = g->nodes()->create<luci::CircleCustomOut>();
+ _add_one = g->nodes()->create<luci::CircleAdd>();
+ _mul = g->nodes()->create<luci::CircleMul>();
+ _mul_half = g->nodes()->create<luci::CircleMul>();
+ _const_sqrt = g->nodes()->create<luci::CircleConst>();
+ _const_one = g->nodes()->create<luci::CircleConst>();
+ _const_half = g->nodes()->create<luci::CircleConst>();
+
+ _mul->fusedActivationFunction(luci::FusedActFunc::NONE);
+ _mul_sqrt->fusedActivationFunction(luci::FusedActFunc::NONE);
+ _mul_half->fusedActivationFunction(luci::FusedActFunc::NONE);
+ _add_one->fusedActivationFunction(luci::FusedActFunc::NONE);
+
+ _ifm->name("ifm");
+ _mul_sqrt->name("mul_sqrt");
+ _erf->name("erf");
+ _erf_out->name("erf_out");
+ _add_one->name("add_one");
+ _mul->name("mul");
+ _mul_half->name("mul_half");
+ _const_one->name("const_one");
+ _const_sqrt->name("const_sqrt");
+ _const_half->name("const_half");
+
+ _erf->custom_code("Erf");
+
+ _const_sqrt->dtype(loco::DataType::FLOAT32);
+ _const_sqrt->size<loco::DataType::FLOAT32>(1);
+ _const_sqrt->shape({1});
+ _const_sqrt->at<loco::DataType::FLOAT32>(0) = sqrtf(0.5f);
+ _const_sqrt->shape_status(luci::ShapeStatus::VALID);
+
+ _const_one->dtype(loco::DataType::FLOAT32);
+ _const_one->size<loco::DataType::FLOAT32>(1);
+ _const_one->shape({1});
+ _const_one->at<loco::DataType::FLOAT32>(0) = 1.0;
+ _const_one->shape_status(luci::ShapeStatus::VALID);
+
+ _const_half->dtype(loco::DataType::FLOAT32);
+ _const_half->size<loco::DataType::FLOAT32>(1);
+ _const_half->shape({1});
+ _const_half->at<loco::DataType::FLOAT32>(0) = 0.5;
+ _const_half->shape_status(luci::ShapeStatus::VALID);
+ }
+
+ void invalid_half() { _const_half->at<loco::DataType::FLOAT32>(0) = 0.1; }
+ void invalid_act() { _add_one->fusedActivationFunction(luci::FusedActFunc::RELU); }
+
+protected:
+ luci::CircleAbs *_ifm = nullptr;
+ luci::CircleMul *_mul_sqrt = nullptr;
+ luci::CircleCustom *_erf = nullptr;
+ luci::CircleCustomOut *_erf_out = nullptr;
+ luci::CircleAdd *_add_one = nullptr;
+ luci::CircleMul *_mul = nullptr;
+ luci::CircleMul *_mul_half = nullptr;
+ luci::CircleConst *_const_sqrt = nullptr;
+ luci::CircleConst *_const_one = nullptr;
+ luci::CircleConst *_const_half = nullptr;
+};
+
+class FuseGeluTestGraph1 : public TestIOGraph, public GeluGraphlet
+{
+public:
+ FuseGeluTestGraph1() = default;
+
+ void init(void)
+ {
+ TestIOGraph::init({1}, {1});
+ GeluGraphlet::init(g());
+
+ _ifm->x(input());
+ _mul_sqrt->x(_ifm);
+ _mul_sqrt->y(_const_sqrt);
+ _erf->inputs(0, _mul_sqrt);
+ _erf_out->input(_erf);
+ _add_one->x(_erf_out);
+ _add_one->y(_const_one);
+ _mul->x(_ifm);
+ _mul->y(_add_one);
+ _mul_half->x(_mul);
+ _mul_half->y(_const_half);
+
+ output()->from(_mul_half);
+ }
+};
+
+class FuseGeluTestGraph2 : public TestIOGraph, public GeluGraphlet
+{
+public:
+ FuseGeluTestGraph2() = default;
+
+ void init(void)
+ {
+ TestIOGraph::init({1}, {1});
+ GeluGraphlet::init(g());
+
+ _ifm->x(input());
+ _mul_sqrt->x(_ifm);
+ _mul_sqrt->y(_const_sqrt);
+ _erf->inputs(0, _mul_sqrt);
+ _erf_out->input(_erf);
+ _add_one->x(_erf_out);
+ _add_one->y(_const_one);
+ _mul_half->x(_ifm);
+ _mul_half->y(_const_half);
+ _mul->x(_mul_half);
+ _mul->y(_add_one);
+
+ output()->from(_mul);
+ }
+};
+
+class FuseGeluTestNegGraph : public TestIOGraph, public GeluGraphlet
+{
+public:
+ FuseGeluTestNegGraph() = default;
+
+ void init(void)
+ {
+ TestIOGraph::init({1}, {1});
+ GeluGraphlet::init(g());
+
+ _ifm->x(input());
+ _mul_sqrt->x(_ifm);
+ // NOTE y is incorrect (should be _const_sqrt)
+ _mul_sqrt->y(_ifm);
+ _erf->inputs(0, _mul_sqrt);
+ _erf_out->input(_erf);
+ _add_one->x(_erf_out);
+ _add_one->y(_const_one);
+ _mul->x(_ifm);
+ _mul->y(_add_one);
+ _mul_half->x(_mul);
+ _mul_half->y(_const_half);
+
+ output()->from(_mul_half);
+ }
+};
+
+} // namespace
+
+TEST(FuseGeluPassTest, name)
+{
+ luci::FuseGeluPass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+TEST(FuseGeluPassTest, fuse_pattern1)
+{
+ FuseGeluTestGraph1 g;
+ luci::FuseGeluPass pass;
+
+ g.init();
+
+ EXPECT_TRUE(pass.run(g.g()));
+}
+
+TEST(FuseGeluPassTest, fuse_pattern2)
+{
+ FuseGeluTestGraph2 g;
+ luci::FuseGeluPass pass;
+
+ g.init();
+
+ EXPECT_TRUE(pass.run(g.g()));
+}
+
+TEST(FuseGeluPassTest, fuse_invalid_half_NEG)
+{
+ FuseGeluTestNegGraph g;
+ luci::FuseGeluPass pass;
+
+ g.init();
+ g.invalid_half();
+
+ EXPECT_FALSE(pass.run(g.g()));
+}
+
+TEST(FuseGeluPassTest, fuse_pattern2_invalid_half_NEG)
+{
+ FuseGeluTestGraph2 g;
+ luci::FuseGeluPass pass;
+
+ g.init();
+ g.invalid_half();
+
+ EXPECT_FALSE(pass.run(g.g()));
+}
+
+TEST(FuseGeluPassTest, fuse_invalid_act_NEG)
+{
+ FuseGeluTestNegGraph g;
+ luci::FuseGeluPass pass;
+
+ g.init();
+ g.invalid_act();
+
+ EXPECT_FALSE(pass.run(g.g()));
+}
+
+TEST(FuseGeluPassTest, fuse_NEG)
+{
+ FuseGeluTestNegGraph g;
+ luci::FuseGeluPass pass;
+
+ g.init();
+
+ EXPECT_FALSE(pass.run(g.g()));
+}
diff --git a/compiler/luci/pass/src/PropagateQParamBackwardPass.cpp b/compiler/luci/pass/src/PropagateQParamBackwardPass.cpp
index e8fa2a478..18617e3b7 100644
--- a/compiler/luci/pass/src/PropagateQParamBackwardPass.cpp
+++ b/compiler/luci/pass/src/PropagateQParamBackwardPass.cpp
@@ -28,6 +28,25 @@
namespace
{
+// Return true if node is a virtual node
+bool virtual_op(const luci::CircleOpcode opcode)
+{
+ switch (opcode)
+ {
+#define CIRCLE_NODE(OPCODE, CIRCLE_CLASS) \
+ case luci::CircleOpcode::OPCODE: \
+ return false;
+#define CIRCLE_VNODE(OPCODE, CIRCLE_CLASS) \
+ case luci::CircleOpcode::OPCODE: \
+ return true;
+#include <luci/IR/CircleNodes.lst>
+#undef CIRCLE_NODE
+#undef CIRCLE_VNODE
+ default:
+ throw std::runtime_error("Unknown opcode detected");
+ }
+}
+
void quant_const_values(luci::CircleConst *const_node, float scaling_factor, float zerop,
loco::DataType quant_type)
{
@@ -448,6 +467,50 @@ struct PropagateQParamBackward final : public luci::CircleNodeMutableVisitor<voi
void visit(luci::CirclePack *node) { propagate_pack_quantparam(node); }
void visit(luci::CirclePadV2 *node) { propagate_pad_v2_quantparam(node); }
+
+ // Propagate qparam for non-value changing Ops
+ // (ex: Reshape, Transpose, etc.)
+ // TODO Add more Ops
+
+ void visit(luci::CircleReshape *node)
+ {
+ auto input_node = loco::must_cast<luci::CircleNode *>(node->tensor());
+
+ // Do not propagate qparam if input node has multiple users
+ if (loco::succs(input_node).size() > 1)
+ return;
+
+ const auto input_opcode = input_node->opcode();
+
+ // Do not propagate qparam if input node is virtual Op (except CIRCLEINPUT)
+ // Why? It is not safe to propagate qparam to some virtual nodes. For example,
+ // const node, multi-out nodes. Let's block them for now.
+ // TODO Revisit this condition
+ if (virtual_op(input_opcode) and input_opcode != luci::CircleOpcode::CIRCLEINPUT)
+ return;
+
+ overwrite_quantparam(node, input_node);
+ }
+
+ void visit(luci::CircleTranspose *node)
+ {
+ auto input_node = loco::must_cast<luci::CircleNode *>(node->a());
+
+ // Do not propagate qparam if input node has multiple users
+ if (loco::succs(input_node).size() > 1)
+ return;
+
+ const auto input_opcode = input_node->opcode();
+
+ // Do not propagate qparam if input node is virtual Op (except CIRCLEINPUT)
+ // Why? It is not safe to propagate qparam to some virtual nodes. For example,
+ // const node, multi-out nodes. Let's block them for now.
+ // TODO Revisit this condition
+ if (virtual_op(input_opcode) and input_opcode != luci::CircleOpcode::CIRCLEINPUT)
+ return;
+
+ overwrite_quantparam(node, input_node);
+ }
};
} // namespace
diff --git a/compiler/luci/pass/src/PropagateQParamBackwardPass.test.cpp b/compiler/luci/pass/src/PropagateQParamBackwardPass.test.cpp
index 33af70449..04573cc45 100644
--- a/compiler/luci/pass/src/PropagateQParamBackwardPass.test.cpp
+++ b/compiler/luci/pass/src/PropagateQParamBackwardPass.test.cpp
@@ -129,6 +129,119 @@ public:
CircleOutput *output = nullptr;
};
+/**
+ * BEFORE
+ *
+ * [Input]
+ * |
+ * [Conv] (qparam 1)
+ * |
+ * [Reshape] (qparam 2)
+ * |
+ * [Output]
+ *
+ * AFTER
+ *
+ * [Input]
+ * |
+ * [Conv] (qparam 2)
+ * |
+ * [Reshape] (qparam 2)
+ * |
+ * [Output]
+ */
+class ConvReshapeGraph
+{
+public:
+ ConvReshapeGraph()
+ {
+ input = g.nodes()->create<luci::CircleInput>();
+ conv = g.nodes()->create<luci::CircleConv2D>();
+ reshape = g.nodes()->create<luci::CircleReshape>();
+ output = g.nodes()->create<luci::CircleOutput>();
+
+ auto graph_input = g.inputs()->create();
+ input->index(graph_input->index());
+ auto graph_output = g.outputs()->create();
+ output->index(graph_output->index());
+
+ set_qparam(conv, 2.0, 2);
+ set_qparam(reshape, 1.0, 1);
+
+ conv->input(input);
+ reshape->tensor(conv);
+ output->from(reshape);
+ }
+
+public:
+ loco::Graph g;
+ luci::CircleInput *input = nullptr;
+ luci::CircleConv2D *conv = nullptr;
+ luci::CircleReshape *reshape = nullptr;
+ luci::CircleOutput *output = nullptr;
+};
+
+/**
+ * BEFORE
+ *
+ * [Input]
+ * |
+ * [Conv] (qparam 1)
+ * |
+ * +---------------------+
+ * | |
+ * [Reshape] (qparam 2) [Output]
+ * |
+ * [Output]
+ *
+ * AFTER (qparam is not propagated as Conv has multiple users)
+ *
+ * [Input]
+ * |
+ * [Conv] (qparam 1)
+ * |
+ * +---------------------+
+ * | |
+ * [Reshape] (qparam 2) [Output]
+ * |
+ * [Output]
+ */
+class ConvReshapeMultiOutGraph
+{
+public:
+ ConvReshapeMultiOutGraph()
+ {
+ input = g.nodes()->create<luci::CircleInput>();
+ conv = g.nodes()->create<luci::CircleConv2D>();
+ reshape = g.nodes()->create<luci::CircleReshape>();
+ output1 = g.nodes()->create<luci::CircleOutput>();
+ output2 = g.nodes()->create<luci::CircleOutput>();
+
+ auto graph_input = g.inputs()->create();
+ input->index(graph_input->index());
+ auto graph_output1 = g.outputs()->create();
+ output1->index(graph_output1->index());
+ auto graph_output2 = g.outputs()->create();
+ output2->index(graph_output2->index());
+
+ set_qparam(conv, 2.0, 2);
+ set_qparam(reshape, 1.0, 1);
+
+ conv->input(input);
+ reshape->tensor(conv);
+ output1->from(reshape);
+ output2->from(conv);
+ }
+
+public:
+ loco::Graph g;
+ luci::CircleInput *input = nullptr;
+ luci::CircleConv2D *conv = nullptr;
+ luci::CircleReshape *reshape = nullptr;
+ luci::CircleOutput *output1 = nullptr;
+ luci::CircleOutput *output2 = nullptr;
+};
+
} // namespace
TEST(PropagateQParamBackwardPassTest, name)
@@ -165,3 +278,33 @@ TEST(PropagateQParamBackwardPassTest, subsequent_propagation)
EXPECT_EQ(3.0, graph.input->quantparam()->scale[0]);
EXPECT_EQ(3, graph.input->quantparam()->zerop[0]);
}
+
+TEST(PropagateQParamBackwardPassTest, reshape)
+{
+ ConvReshapeGraph graph;
+
+ EXPECT_NE(graph.conv->quantparam()->scale, graph.reshape->quantparam()->scale);
+ EXPECT_NE(graph.conv->quantparam()->zerop, graph.reshape->quantparam()->zerop);
+
+ luci::PropagateQParamBackwardPass pass(loco::DataType::U8);
+
+ pass.run(&graph.g);
+
+ EXPECT_EQ(graph.conv->quantparam()->scale, graph.reshape->quantparam()->scale);
+ EXPECT_EQ(graph.conv->quantparam()->zerop, graph.reshape->quantparam()->zerop);
+}
+
+TEST(PropagateQParamBackwardPassTest, reshape_multi_use_NEG)
+{
+ ConvReshapeMultiOutGraph graph;
+
+ EXPECT_NE(graph.conv->quantparam()->scale, graph.reshape->quantparam()->scale);
+ EXPECT_NE(graph.conv->quantparam()->zerop, graph.reshape->quantparam()->zerop);
+
+ luci::PropagateQParamBackwardPass pass(loco::DataType::U8);
+
+ pass.run(&graph.g);
+
+ EXPECT_NE(graph.conv->quantparam()->scale, graph.reshape->quantparam()->scale);
+ EXPECT_NE(graph.conv->quantparam()->zerop, graph.reshape->quantparam()->zerop);
+}
diff --git a/compiler/luci/pass/src/QuantizationUtils.cpp b/compiler/luci/pass/src/QuantizationUtils.cpp
index 45d229a0b..3e3cdde34 100644
--- a/compiler/luci/pass/src/QuantizationUtils.cpp
+++ b/compiler/luci/pass/src/QuantizationUtils.cpp
@@ -73,14 +73,14 @@ void asymmetric_wquant_with_minmax_per_layer(CircleConst *node, float min, float
}
void symmetric_wquant_with_minmax_per_layer(CircleConst *node, float min, float max,
- float &scaling_factor, int64_t &zp, float &nudged_min,
+ float &scaling_factor, float &nudged_min,
float &nudged_max)
{
const int32_t kMaxScale = std::numeric_limits<int16_t>::max();
const int32_t kMinScale = -kMaxScale;
uint32_t size = node->size<loco::DataType::FLOAT32>();
- compute_sym_scale_zp(min, max, scaling_factor, zp, nudged_min, nudged_max);
+ compute_sym_scale(min, max, scaling_factor, nudged_min, nudged_max);
const float scaling_factor_inv = 1.0 / scaling_factor;
std::vector<int32_t> quantized_values(size);
for (uint32_t i = 0; i < size; ++i)
@@ -101,12 +101,14 @@ void symmetric_wquant_with_minmax_per_layer(CircleConst *node, float min, float
}
}
-void compute_sym_scale_zp(float min, float max, float &scaling_factor, int64_t &zp,
- float &nudged_min, float &nudged_max)
+void compute_sym_scale(float min, float max, float &scaling_factor, float &nudged_min,
+ float &nudged_max, loco::DataType out_type)
{
assert(min <= max);
+ assert(out_type == loco::DataType::S8 || out_type == loco::DataType::S16);
- const int32_t kMaxScale = std::numeric_limits<int16_t>::max();
+ const int32_t kMaxScale = (out_type == loco::DataType::S16) ? std::numeric_limits<int16_t>::max()
+ : std::numeric_limits<int8_t>::max();
const int32_t kMinScale = -kMaxScale;
const double qmin_double = kMinScale;
const double qmax_double = kMaxScale;
@@ -126,10 +128,9 @@ void compute_sym_scale_zp(float min, float max, float &scaling_factor, int64_t &
: scale_factor_from_max_side;
// protect scale from being very low to avoid overflow/underflow
- if (scaling_factor < 1e-8)
- scaling_factor = 1e-8;
+ const float kMinScalingFactor = (out_type == loco::DataType::S16) ? 1e-8 : 1e-5;
+ scaling_factor = std::max(scaling_factor, kMinScalingFactor);
- zp = 0;
nudged_min = static_cast<float>(qmin_double * scaling_factor);
nudged_max = static_cast<float>(qmax_double * scaling_factor);
}
@@ -424,7 +425,7 @@ void quant_const(luci::CircleConst *node, loco::DataType quant_type)
nudged_max);
break;
case loco::DataType::S16:
- symmetric_wquant_with_minmax_per_layer(node, min, max, scaling_factor, zp, nudged_min,
+ symmetric_wquant_with_minmax_per_layer(node, min, max, scaling_factor, nudged_min,
nudged_max);
break;
default:
diff --git a/compiler/luci/pass/src/QuantizationUtils.h b/compiler/luci/pass/src/QuantizationUtils.h
index 0720c9839..93c4045b5 100644
--- a/compiler/luci/pass/src/QuantizationUtils.h
+++ b/compiler/luci/pass/src/QuantizationUtils.h
@@ -23,9 +23,9 @@
namespace luci
{
-// Compute scale/zp using given min/max for symmetric quantization (int16)
-void compute_sym_scale_zp(float min, float max, float &scaling_factor, int64_t &zp,
- float &nudged_min, float &nudged_max);
+// Compute scale using given min/max for symmetric quantization (int8/int16)
+void compute_sym_scale(float min, float max, float &scaling_factor, float &nudged_min,
+ float &nudged_max, loco::DataType out_type = loco::DataType::S16);
// Compute scale/zp using given min/max for asymmetric quantization (uint8)
void compute_asym_scale_zp(float min, float max, float &scaling_factor, int64_t &zp,
@@ -40,7 +40,7 @@ void asymmetric_wquant_with_minmax_per_layer(CircleConst *node, float min, float
// Symmetric per-layer quantization of weights (const tensor) using given min/max values
// NOTE: in-place update of node data
void symmetric_wquant_with_minmax_per_layer(CircleConst *node, float min, float max,
- float &scaling_factor, int64_t &zp, float &nudged_min,
+ float &scaling_factor, float &nudged_min,
float &nudged_max);
// Helper function to get channel dimension
diff --git a/compiler/luci/pass/src/QuantizeActivation.cpp b/compiler/luci/pass/src/QuantizeActivation.cpp
index 214e61c1e..913450083 100644
--- a/compiler/luci/pass/src/QuantizeActivation.cpp
+++ b/compiler/luci/pass/src/QuantizeActivation.cpp
@@ -78,7 +78,7 @@ void QuantizeActivation::visit(luci::CircleNode *node)
}
else
{
- compute_sym_scale_zp(min, max, scaling_factor, zp, nudged_min, nudged_max);
+ compute_sym_scale(min, max, scaling_factor, nudged_min, nudged_max);
node->dtype(loco::DataType::S16);
}
@@ -171,7 +171,10 @@ void QuantizeConstInputActivation::visit(luci::CircleNode *node)
auto input_node = node->arg(i);
auto const_node = dynamic_cast<luci::CircleConst *>(input_node);
if (const_node != nullptr)
- throw std::runtime_error("Unsupported Op for const inputs");
+ {
+ std::string msg = "Unsupported Op for const inputs: " + node->name();
+ throw std::runtime_error(msg);
+ }
}
}
@@ -221,6 +224,7 @@ QUANTIZE_SINGLE_CONST_INPUT(luci::CircleElu, features)
QUANTIZE_SINGLE_CONST_INPUT(luci::CircleExp, x)
QUANTIZE_SINGLE_CONST_INPUT(luci::CircleFloor, x)
QUANTIZE_SINGLE_CONST_INPUT(luci::CircleGather, params)
+QUANTIZE_SINGLE_CONST_INPUT(luci::CircleGelu, features)
QUANTIZE_SINGLE_CONST_INPUT(luci::CircleLocalResponseNormalization, input)
QUANTIZE_SINGLE_CONST_INPUT(luci::CircleLogistic, x)
QUANTIZE_SINGLE_CONST_INPUT(luci::CircleMean, input)
@@ -242,6 +246,7 @@ QUANTIZE_SINGLE_CONST_INPUT(luci::CircleSpaceToDepth, input)
QUANTIZE_SINGLE_CONST_INPUT(luci::CircleSplit, input)
QUANTIZE_SINGLE_CONST_INPUT(luci::CircleSplitV, input)
QUANTIZE_SINGLE_CONST_INPUT(luci::CircleSqrt, x)
+QUANTIZE_SINGLE_CONST_INPUT(luci::CircleSqueeze, input)
QUANTIZE_SINGLE_CONST_INPUT(luci::CircleStridedSlice, input)
QUANTIZE_SINGLE_CONST_INPUT(luci::CircleSum, input)
QUANTIZE_SINGLE_CONST_INPUT(luci::CircleTanh, x)
@@ -256,6 +261,7 @@ QUANTIZE_TWO_CONST_INPUTS(luci::CircleBatchMatMul, x, y)
QUANTIZE_TWO_CONST_INPUTS(luci::CircleDiv, x, y)
QUANTIZE_TWO_CONST_INPUTS(luci::CircleEqual, x, y)
QUANTIZE_TWO_CONST_INPUTS(luci::CircleFloorDiv, x, y)
+QUANTIZE_TWO_CONST_INPUTS(luci::CircleFloorMod, x, y)
QUANTIZE_TWO_CONST_INPUTS(luci::CircleGreater, x, y)
QUANTIZE_TWO_CONST_INPUTS(luci::CircleGreaterEqual, x, y)
QUANTIZE_TWO_CONST_INPUTS(luci::CircleLess, x, y)
diff --git a/compiler/luci/pass/src/QuantizeActivation.h b/compiler/luci/pass/src/QuantizeActivation.h
index c6c991a76..ba3bc59f2 100644
--- a/compiler/luci/pass/src/QuantizeActivation.h
+++ b/compiler/luci/pass/src/QuantizeActivation.h
@@ -111,6 +111,7 @@ private:
void visit(luci::CircleExp *node);
void visit(luci::CircleFloor *node);
void visit(luci::CircleGather *node);
+ void visit(luci::CircleGelu *node);
void visit(luci::CircleLocalResponseNormalization *node);
void visit(luci::CircleLogistic *node);
void visit(luci::CircleMean *node);
@@ -132,6 +133,7 @@ private:
void visit(luci::CircleSplit *node);
void visit(luci::CircleSplitV *node);
void visit(luci::CircleSqrt *node);
+ void visit(luci::CircleSqueeze *node);
void visit(luci::CircleStridedSlice *node);
void visit(luci::CircleSum *node);
void visit(luci::CircleTanh *node);
@@ -146,6 +148,7 @@ private:
void visit(luci::CircleDiv *node);
void visit(luci::CircleEqual *node);
void visit(luci::CircleFloorDiv *node);
+ void visit(luci::CircleFloorMod *node);
void visit(luci::CircleGreater *node);
void visit(luci::CircleGreaterEqual *node);
void visit(luci::CircleLess *node);
diff --git a/compiler/luci/pass/src/QuantizeBias.test.cpp b/compiler/luci/pass/src/QuantizeBias.test.cpp
index 0104a191b..9030f59e9 100644
--- a/compiler/luci/pass/src/QuantizeBias.test.cpp
+++ b/compiler/luci/pass/src/QuantizeBias.test.cpp
@@ -16,6 +16,8 @@
#include "QuantizeBias.h"
+#include "helpers/CreateCircleConst.h"
+
#include <luci/test/TestIOGraph.h>
#include <luci/IR/CircleNodes.h>
#include <luci/IR/CircleQuantParam.h>
@@ -29,51 +31,6 @@ namespace
using namespace luci::test;
-// TODO Reduce duplicate codes in ResolveCustomOpMatMulPass.cpp
-template <typename T>
-luci::CircleConst *create_const_node(loco::Graph *g, const loco::DataType dtype,
- const std::vector<uint32_t> &shape, T value)
-{
- auto node = g->nodes()->create<luci::CircleConst>();
- node->dtype(dtype);
- node->rank(shape.size());
-
- uint32_t size = 1;
- for (uint32_t i = 0; i < shape.size(); ++i)
- {
- node->dim(i) = shape.at(i);
- size *= shape.at(i);
- }
- node->shape_status(luci::ShapeStatus::VALID);
-
-#define INIT_VALUES(DT) \
- { \
- node->size<DT>(size); \
- for (uint32_t i = 0; i < size; ++i) \
- node->at<DT>(i) = value; \
- }
-
- switch (dtype)
- {
- case loco::DataType::U8:
- INIT_VALUES(loco::DataType::U8);
- break;
- case loco::DataType::S16:
- INIT_VALUES(loco::DataType::S16);
- break;
- case loco::DataType::S32:
- INIT_VALUES(loco::DataType::S32);
- break;
- case loco::DataType::FLOAT32:
- INIT_VALUES(loco::DataType::FLOAT32)
- break;
- default:
- INTERNAL_EXN("create_const_node called with unsupported type");
- break;
- }
- return node;
-}
-
/**
* Simple graph for test
*
diff --git a/compiler/luci/pass/src/QuantizeDequantizeWeightsPass.cpp b/compiler/luci/pass/src/QuantizeDequantizeWeightsPass.cpp
index ef047d35d..f8989c9e0 100644
--- a/compiler/luci/pass/src/QuantizeDequantizeWeightsPass.cpp
+++ b/compiler/luci/pass/src/QuantizeDequantizeWeightsPass.cpp
@@ -110,8 +110,8 @@ void cal_minmax_per_channel(CircleConst *node, std::vector<float> &min, std::vec
}
void sym_wquant_per_channel(CircleConst *node, std::vector<float> &min, std::vector<float> &max,
- std::vector<float> &scaling_factor, std::vector<int64_t> &zp,
- std::vector<float> &nudged_min, std::vector<float> &nudged_max)
+ std::vector<float> &scaling_factor, std::vector<float> &nudged_min,
+ std::vector<float> &nudged_max)
{
assert(node->dtype() == loco::DataType::FLOAT32);
const int32_t kMaxScale = std::numeric_limits<int16_t>::max();
@@ -122,7 +122,7 @@ void sym_wquant_per_channel(CircleConst *node, std::vector<float> &min, std::vec
for (size_t i = 0; i < min.size(); ++i)
{
- compute_sym_scale_zp(min[i], max[i], scaling_factor[i], zp[i], nudged_min[i], nudged_max[i]);
+ compute_sym_scale(min[i], max[i], scaling_factor[i], nudged_min[i], nudged_max[i]);
}
auto quantize = [&](uint32_t *indices, loco::TensorShape &dimension, int channel_dim_index) {
@@ -322,7 +322,7 @@ private:
}
else
{
- sym_wquant_per_channel(weights, min, max, scaling_factor, zp, nudged_min, nudged_max);
+ sym_wquant_per_channel(weights, min, max, scaling_factor, nudged_min, nudged_max);
sym_wdequant_per_channel(weights, scaling_factor);
}
diff --git a/compiler/luci/pass/src/QuantizePreCheckerPass.test.cpp b/compiler/luci/pass/src/QuantizePreCheckerPass.test.cpp
index 788353cd8..8f6a96f33 100644
--- a/compiler/luci/pass/src/QuantizePreCheckerPass.test.cpp
+++ b/compiler/luci/pass/src/QuantizePreCheckerPass.test.cpp
@@ -206,6 +206,7 @@ public:
transpose_conv->outBackprop(input_1);
transpose_conv->filter(filter);
transpose_conv->inputSizes(input_sizes);
+ transpose_conv->fusedActivationFunction(luci::FusedActFunc::NONE);
if (make_valid)
{
diff --git a/compiler/luci/pass/src/QuantizeWeights.cpp b/compiler/luci/pass/src/QuantizeWeights.cpp
index 29cdaffff..59329c19e 100644
--- a/compiler/luci/pass/src/QuantizeWeights.cpp
+++ b/compiler/luci/pass/src/QuantizeWeights.cpp
@@ -92,9 +92,8 @@ void asym_wquant_per_channel(CircleConst *node, std::vector<float> &min,
// TODO Reduce duplicate code with QuantizeDequantizeWeights
void sym_wquant_per_channel(CircleConst *node, std::vector<float> &min, std::vector<float> &max,
- std::vector<float> &scaling_factor, std::vector<int64_t> &zp,
- std::vector<float> &nudged_min, std::vector<float> &nudged_max,
- int32_t &channel_dim_index)
+ std::vector<float> &scaling_factor, std::vector<float> &nudged_min,
+ std::vector<float> &nudged_max, int32_t &channel_dim_index)
{
assert(node->dtype() == loco::DataType::FLOAT32);
const int32_t kMaxScale = std::numeric_limits<int16_t>::max();
@@ -105,7 +104,7 @@ void sym_wquant_per_channel(CircleConst *node, std::vector<float> &min, std::vec
for (size_t i = 0; i < min.size(); ++i)
{
- compute_sym_scale_zp(min[i], max[i], scaling_factor[i], zp[i], nudged_min[i], nudged_max[i]);
+ compute_sym_scale(min[i], max[i], scaling_factor[i], nudged_min[i], nudged_max[i]);
}
auto quantize = [&](uint32_t *indices, loco::TensorShape &dimension, int channel_dim_index) {
@@ -383,7 +382,7 @@ void QuantizeWeights::quantize_weights(luci::CircleConst *weights)
}
else
{
- sym_wquant_per_channel(weights, min, max, scaling_factor, zp, nudged_min, nudged_max,
+ sym_wquant_per_channel(weights, min, max, scaling_factor, nudged_min, nudged_max,
channel_dim_index);
}
diff --git a/compiler/luci/pass/src/QuantizeWeightsOnly.cpp b/compiler/luci/pass/src/QuantizeWeightsOnly.cpp
new file mode 100644
index 000000000..e69a7b6a8
--- /dev/null
+++ b/compiler/luci/pass/src/QuantizeWeightsOnly.cpp
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "QuantizeWeightsOnly.h"
+#include "QuantizationUtils.h"
+
+#include <luci/Service/Nodes/CircleConst.h>
+#include <luci/Log.h>
+
+#include <cmath>
+#include <vector>
+#include <functional>
+#include <limits>
+
+using namespace luci;
+
+namespace
+{
+
+using IterFunc = std::function<void(uint32_t *, loco::TensorShape &, int32_t)>;
+
+void iterate_per_channel(CircleConst *node, int32_t &channel_dim_index, IterFunc func)
+{
+ loco::TensorShape dimension;
+ dimension.rank(4);
+ uint32_t indices[4] = {
+ 0,
+ };
+
+ if (!get_channel_dim_index(node, dimension, channel_dim_index))
+ {
+ assert(false);
+ return;
+ }
+
+ for (indices[0] = 0; indices[0] < dimension.dim(0).value(); indices[0]++)
+ {
+ for (indices[1] = 0; indices[1] < dimension.dim(1).value(); indices[1]++)
+ {
+ for (indices[2] = 0; indices[2] < dimension.dim(2).value(); indices[2]++)
+ {
+ for (indices[3] = 0; indices[3] < dimension.dim(3).value(); indices[3]++)
+ {
+ func(indices, dimension, channel_dim_index);
+ }
+ }
+ }
+ }
+}
+
+// TODO Reduce duplicate code with QuantizeDequantizeWeights
+template <loco::DataType out_type>
+void sym_wquant_per_channel(CircleConst *node, std::vector<float> &min, std::vector<float> &max,
+ std::vector<float> &scaling_factor, std::vector<float> &nudged_min,
+ std::vector<float> &nudged_max, int32_t &channel_dim_index)
+{
+ assert(node->dtype() == loco::DataType::FLOAT32);
+ assert(out_type == loco::DataType::S8 || out_type == loco::DataType::S16);
+ const int32_t kMaxScale = (out_type == loco::DataType::S8) ? std::numeric_limits<int8_t>::max()
+ : std::numeric_limits<int16_t>::max();
+ const int32_t kMinScale = -kMaxScale;
+
+ uint32_t size = node->size<loco::DataType::FLOAT32>();
+ std::vector<int32_t> quantized_values(size);
+
+ for (size_t i = 0; i < min.size(); ++i)
+ {
+ compute_sym_scale(min[i], max[i], scaling_factor[i], nudged_min[i], nudged_max[i], out_type);
+ }
+
+ auto quantize = [&](uint32_t *indices, loco::TensorShape &dimension, int channel_dim_index) {
+ int channel_idx = indices[channel_dim_index];
+ const float scaling_factor_inv = 1.0 / scaling_factor[channel_idx];
+ auto data = node->at<loco::DataType::FLOAT32>(cal_offset(dimension, indices));
+ data = data < nudged_min[channel_idx] ? nudged_min[channel_idx] : data;
+ data = data > nudged_max[channel_idx] ? nudged_max[channel_idx] : data;
+ quantized_values[cal_offset(dimension, indices)] =
+ static_cast<int32_t>(std::round(data * scaling_factor_inv));
+ };
+
+ iterate_per_channel(node, channel_dim_index, quantize);
+
+ node->dtype(out_type); // change the type of tensor
+ node->size<out_type>(size); // resize tensor
+ for (uint32_t i = 0; i < size; ++i)
+ {
+ node->at<out_type>(i) = std::min(kMaxScale, std::max(kMinScale, quantized_values[i]));
+ }
+}
+
+void cal_minmax_per_channel(CircleConst *node, std::vector<float> &min, std::vector<float> &max,
+ int32_t &channel_dim_index)
+{
+ loco::TensorShape dimension;
+ dimension.rank(4);
+
+ if (!get_channel_dim_index(node, dimension, channel_dim_index))
+ {
+ throw std::runtime_error("Failed to find channel index in " + node->name());
+ }
+ auto size = dimension.dim(channel_dim_index).value();
+
+ std::vector<bool> has_min_max_value(size, false);
+ min.resize(size);
+ max.resize(size);
+
+ auto cal_minmax = [&](uint32_t *indices, loco::TensorShape &dimension, int channel_dim_index) {
+ int channel_idx = indices[channel_dim_index];
+ auto data = node->at<loco::DataType::FLOAT32>(cal_offset(dimension, indices));
+ if (has_min_max_value[channel_idx])
+ {
+ min[channel_idx] = data < min[channel_idx] ? data : min[channel_idx];
+ max[channel_idx] = data > max[channel_idx] ? data : max[channel_idx];
+ }
+ else
+ {
+ min[channel_idx] = data;
+ max[channel_idx] = data;
+ has_min_max_value[channel_idx] = true;
+ }
+ };
+
+ iterate_per_channel(node, channel_dim_index, cal_minmax);
+}
+
+} // namespace
+
+namespace luci
+{
+
+void QuantizeWeightsOnly::quantize_weights(luci::CircleConst *weights)
+{
+ // Find min/max per channel-wise
+ if (granularity == QuantizationGranularity::ChannelWise)
+ {
+ auto quantparam = weights->quantparam();
+ if (quantparam == nullptr)
+ {
+ // Find min/max on the fly
+ // NOTE This is for the case when QuantizeDequantizeWeights is skipped
+ // TODO Reduce duplicate codes
+ std::vector<float> min;
+ std::vector<float> max;
+ int32_t channel_dim_index = 0;
+
+ cal_minmax_per_channel(weights, min, max, channel_dim_index);
+
+ std::vector<float> nudged_min(min.size());
+ std::vector<float> nudged_max(min.size());
+ std::vector<float> scaling_factor(min.size());
+ std::vector<int64_t> zp(min.size());
+
+ if (output_type == loco::DataType::S8)
+ {
+ sym_wquant_per_channel<loco::DataType::S8>(weights, min, max, scaling_factor, nudged_min,
+ nudged_max, channel_dim_index);
+ }
+ else if (output_type == loco::DataType::S16)
+ {
+ sym_wquant_per_channel<loco::DataType::S16>(weights, min, max, scaling_factor, nudged_min,
+ nudged_max, channel_dim_index);
+ }
+ else
+ {
+ throw std::runtime_error("Weights-only quantization supports s8 and s16");
+ }
+
+ auto quantparam = std::make_unique<CircleQuantParam>();
+ quantparam->scale = scaling_factor;
+ quantparam->zerop = zp;
+ quantparam->quantized_dimension = channel_dim_index;
+ weights->quantparam(std::move(quantparam));
+
+ return;
+ }
+ }
+ else
+ throw std::runtime_error("Weights-only quantization does not support layer-wise");
+}
+
+void QuantizeWeightsOnly::visit(luci::CircleConv2D *node)
+{
+ LOGGER(l);
+ INFO(l) << "QuantizeWeightsOnly visits node: " << node->name() << std::endl;
+
+ auto weights = loco::must_cast<luci::CircleConst *>(node->filter());
+ if (!is_quantized(weights))
+ {
+ auto new_weights = luci::clone(weights);
+ node->filter(new_weights);
+ quantize_weights(new_weights);
+ }
+}
+
+void QuantizeWeightsOnly::visit(luci::CircleDepthwiseConv2D *node)
+{
+ LOGGER(l);
+ INFO(l) << "QuantizeWeightsOnly visits node: " << node->name() << std::endl;
+
+ auto weights = loco::must_cast<luci::CircleConst *>(node->filter());
+ if (!is_quantized(weights))
+ {
+ auto new_weights = luci::clone(weights);
+ node->filter(new_weights);
+ quantize_weights(new_weights);
+ }
+}
+
+void QuantizeWeightsOnly::visit(luci::CircleNode *) {}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/QuantizeWeightsOnly.h b/compiler/luci/pass/src/QuantizeWeightsOnly.h
new file mode 100644
index 000000000..ff6ad3261
--- /dev/null
+++ b/compiler/luci/pass/src/QuantizeWeightsOnly.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_QUANTIZE_WEIGHTS_ONLY_H__
+#define __LUCI_QUANTIZE_WEIGHTS_ONLY_H__
+
+#include <luci/Pass/QuantizationParameters.h>
+#include <luci/IR/CircleNodeVisitor.h>
+
+namespace luci
+{
+
+/**
+ * @brief QuantizeWeightsOnly quantizes tensors for weights
+ * @details Find min/max values on the fly and then quantize
+ */
+struct QuantizeWeightsOnly final : public luci::CircleNodeMutableVisitor<void>
+{
+ QuantizeWeightsOnly(loco::DataType input, loco::DataType output, QuantizationGranularity gr)
+ : input_type(input), output_type(output), granularity(gr)
+ {
+ }
+
+ loco::DataType input_type;
+ loco::DataType output_type;
+ QuantizationGranularity granularity;
+
+private:
+ void quantize_weights(luci::CircleConst *weights);
+
+ void visit(luci::CircleConv2D *node);
+ void visit(luci::CircleDepthwiseConv2D *node);
+ void visit(luci::CircleNode *);
+};
+
+} // namespace luci
+
+#endif // __LUCI_QUANTIZE_WEIGHTS_ONLY_H__
diff --git a/compiler/luci/pass/src/QuantizeWeightsPass.cpp b/compiler/luci/pass/src/QuantizeWeightsPass.cpp
new file mode 100644
index 000000000..9ac203e77
--- /dev/null
+++ b/compiler/luci/pass/src/QuantizeWeightsPass.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/QuantizeWeightsPass.h"
+#include "QuantizeWeightsOnly.h"
+#include "QuantizationUtils.h"
+
+#include <luci/Log.h>
+
+namespace luci
+{
+
+bool QuantizeWeightsPass::run(loco::Graph *g)
+{
+ LOGGER(l);
+ INFO(l) << "QuantizeWeightsPass Start" << std::endl;
+
+ if (_ctx->input_model_dtype != loco::DataType::FLOAT32)
+ throw std::runtime_error("Weights-only quantization supports float32 input only");
+
+ // Quantize weights
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ auto circle_node = loco::must_cast<luci::CircleNode *>(node);
+ QuantizeWeightsOnly qw(_ctx->input_model_dtype, _ctx->output_model_dtype, _ctx->granularity);
+ circle_node->accept(&qw);
+ }
+
+ INFO(l) << "QuantizeWeightsPass End" << std::endl;
+ return false; // one time run
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/QuantizeWeightsPass.test.cpp b/compiler/luci/pass/src/QuantizeWeightsPass.test.cpp
new file mode 100644
index 000000000..058e029ab
--- /dev/null
+++ b/compiler/luci/pass/src/QuantizeWeightsPass.test.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/QuantizeWeightsPass.h"
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+struct QuantizeWeightsPassTest : public ::testing::Test
+{
+ /**
+ * nconv graph
+ *
+ * [CircleInput]
+ * |
+ * |
+ * [CircleConv2D]
+ * |
+ * |
+ * [CircleOutput]
+ */
+ void MakeGraph()
+ {
+ const int N = 1;
+ const int H = 4;
+ const int W = 4;
+ const int C = 3; // IC = OC
+
+ // graph input and output
+ auto graph_input = _g.inputs()->create();
+ auto graph_output = _g.outputs()->create();
+
+ // CircleInput
+ auto input = _g.nodes()->create<luci::CircleInput>();
+ input->index(graph_input->index());
+ input->shape({N, H, W, C});
+ input->dtype(loco::DataType::FLOAT32);
+ input->name("input");
+
+ // CircleConv2D
+ auto conv = _g.nodes()->create<luci::CircleConv2D>();
+ conv->input(input);
+ auto bias = _g.nodes()->create<luci::CircleConst>();
+ bias->dtype(loco::DataType::FLOAT32);
+ bias->shape({C});
+ bias->name("conv_bias");
+ conv->bias(bias);
+ auto weight = _g.nodes()->create<luci::CircleConst>();
+ weight->dtype(loco::DataType::FLOAT32);
+ weight->shape({C, H, W, C});
+ weight->size<loco::DataType::FLOAT32>(C * H * W * C);
+ conv->filter(weight);
+ conv->padding(luci::Padding::SAME);
+ conv->fusedActivationFunction(luci::FusedActFunc::NONE);
+ conv->dtype(loco::DataType::FLOAT32);
+ conv->name("nconv");
+
+ // CircleOutput
+ auto output = _g.nodes()->create<luci::CircleOutput>();
+ output->index(graph_output->index());
+ output->from(conv);
+ output->shape({N, H, W, C});
+ output->dtype(loco::DataType::FLOAT32);
+ output->name("output");
+ }
+ virtual void SetUp() { MakeGraph(); }
+ loco::Graph _g;
+};
+
+} // namespace
+
+TEST_F(QuantizeWeightsPassTest, name)
+{
+ luci::QuantizeWeightsPass pass(loco::DataType::FLOAT32, loco::DataType::S8,
+ luci::QuantizationGranularity::ChannelWise);
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+TEST_F(QuantizeWeightsPassTest, name_ctx)
+{
+ auto ctx = std::make_unique<luci::QuantizeWeightsPass::Context>();
+ {
+ ctx->input_model_dtype = loco::DataType::FLOAT32;
+ ctx->output_model_dtype = loco::DataType::S8;
+ ctx->granularity = luci::QuantizationGranularity::ChannelWise;
+ }
+
+ luci::QuantizeWeightsPass pass(std::move(ctx));
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+TEST_F(QuantizeWeightsPassTest, run_input_U8_NEG)
+{
+ loco::Graph g;
+ luci::QuantizeWeightsPass pass(loco::DataType::U8, loco::DataType::S8,
+ luci::QuantizationGranularity::ChannelWise);
+ EXPECT_THROW(pass.run(&_g), std::runtime_error);
+}
+
+TEST_F(QuantizeWeightsPassTest, run_output_f32_NEG)
+{
+ loco::Graph g;
+ luci::QuantizeWeightsPass pass(loco::DataType::FLOAT32, loco::DataType::FLOAT32,
+ luci::QuantizationGranularity::ChannelWise);
+ EXPECT_THROW(pass.run(&_g), std::runtime_error);
+}
diff --git a/compiler/luci/pass/src/QuantizeWithMinMaxPass.cpp b/compiler/luci/pass/src/QuantizeWithMinMaxPass.cpp
index c68e06712..4f4edaf36 100644
--- a/compiler/luci/pass/src/QuantizeWithMinMaxPass.cpp
+++ b/compiler/luci/pass/src/QuantizeWithMinMaxPass.cpp
@@ -101,7 +101,7 @@ luci::CircleQuantize *create_quantize_op(luci::CircleNode *node, loco::DataType
else
{
assert(out_type == loco::DataType::S16);
- compute_sym_scale_zp(min, max, scaling_factor, zp, nudged_min, nudged_max);
+ compute_sym_scale(min, max, scaling_factor, nudged_min, nudged_max);
}
auto quantparam = std::make_unique<CircleQuantParam>();
@@ -271,6 +271,7 @@ private:
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleFloor, x)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleFullyConnected, input)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleGather, params)
+ INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleGelu, features)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleInstanceNorm, input)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleLeakyRelu, features)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleLocalResponseNormalization, input)
@@ -433,7 +434,7 @@ void QuantizeWithMinMaxPass::set_input_type(loco::Graph *g) const
else
{
assert(user_given_dtype == loco::DataType::S16);
- compute_sym_scale_zp(min, max, scaling_factor, zp, nudged_min, nudged_max);
+ compute_sym_scale(min, max, scaling_factor, nudged_min, nudged_max);
}
input->quantparam()->scale[0] = scaling_factor;
input->quantparam()->zerop[0] = zp;
@@ -479,15 +480,15 @@ void QuantizeWithMinMaxPass::set_output_type(loco::Graph *g) const
if (user_given_dtype == loco::DataType::FLOAT32)
{
auto dequant_op = create_dequantize(from);
- loco::replace(from).with(dequant_op);
dequant_op->input(from);
+ output->from(dequant_op);
}
else
{
// Insert Quantize Op for non-float32 output_type
auto quant_op = create_quantize_op(from, user_given_dtype);
- loco::replace(from).with(quant_op);
quant_op->input(from);
+ output->from(quant_op);
// TODO Set a proper origin (Quantize should have its own Origin)
luci::add_origin(quant_op, luci::get_origin(from));
@@ -629,6 +630,13 @@ bool QuantizeWithMinMaxPass::run(loco::Graph *g)
for (auto node : loco::active_nodes(loco::output_nodes(g)))
{
auto circle_node = loco::must_cast<luci::CircleNode *>(node);
+
+ // At this point, all activations have to be quantized.
+ // Un-quantized nodes are not the quantization target (ex: int32 tensor),
+ // so we skip them
+ if (circle_node->quantparam() == nullptr)
+ continue;
+
QuantizeSpecialActivation qsa(_ctx->input_model_dtype, quantize_dtype(circle_node));
circle_node->accept(&qsa);
}
diff --git a/compiler/luci/pass/src/QuantizedModelVerifier.test.cpp b/compiler/luci/pass/src/QuantizedModelVerifier.test.cpp
index 05ec31727..ae02edb3d 100644
--- a/compiler/luci/pass/src/QuantizedModelVerifier.test.cpp
+++ b/compiler/luci/pass/src/QuantizedModelVerifier.test.cpp
@@ -66,6 +66,8 @@ template <Type T> luci::CircleConst *create_dummy_const(loco::Graph *g, luci::te
// Fill with index
node->at<T>(i) = static_cast<int16_t>(i);
break;
+ default:
+ break;
}
}
}
@@ -470,15 +472,15 @@ public:
void init(void) override
{
TestIOGraph::init({32}, {32});
- _begin = g()->nodes()->create<luci::CircleConst>();
+ _begin = g()->nodes()->template create<luci::CircleConst>();
{
_begin->dtype(indexT);
}
- _size = g()->nodes()->create<luci::CircleConst>();
+ _size = g()->nodes()->template create<luci::CircleConst>();
{
_size->dtype(indexT);
}
- _slice = g()->nodes()->create<luci::CircleSlice>();
+ _slice = g()->nodes()->template create<luci::CircleSlice>();
{
_slice->input(input());
_slice->begin(_begin);
@@ -595,6 +597,31 @@ private:
luci::CircleConst *_strides = nullptr;
};
+class SumTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({4, 3, 2}, {2});
+
+ _axis = create_const<Type::S32, int32_t>(g(), {2}, {1, 0});
+ _sum = g()->nodes()->create<luci::CircleSum>();
+ {
+ _sum->input(input());
+ _sum->reduction_indices(_axis);
+ _sum->name("test");
+ _sum->keep_dims(false);
+ }
+ output()->from(_sum);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+private:
+ luci::CircleSum *_sum = nullptr;
+ luci::CircleConst *_axis = nullptr;
+};
+
class ReshapeTestGraph final : public SimpleTestGraph
{
public:
@@ -669,11 +696,11 @@ public:
TestIOGraph::init({32}, {1});
// output dtype is float by default, but ArgMax should have indexType (s32/s64)
output()->dtype(indexT);
- _dimension = g()->nodes()->create<luci::CircleConst>();
+ _dimension = g()->nodes()->template create<luci::CircleConst>();
{
_dimension->dtype(indexT);
}
- _argmax = g()->nodes()->create<luci::CircleArgMax>();
+ _argmax = g()->nodes()->template create<luci::CircleArgMax>();
{
_argmax->input(input());
_argmax->dimension(_dimension);
@@ -978,7 +1005,7 @@ public:
TestIOGraph::init({32}, {32});
output()->dtype(loco::DataType::BOOL);
_y = create_dummy_const<Type::FLOAT32>(g(), {32});
- _op = g()->nodes()->create<Op>();
+ _op = g()->nodes()->template create<Op>();
{
_op->x(input());
_op->y(_y);
@@ -1011,7 +1038,7 @@ public:
input()->dtype(loco::DataType::BOOL);
output()->dtype(loco::DataType::BOOL);
_y = create_dummy_const<Type::BOOL>(g(), {32});
- _op = g()->nodes()->create<Op>();
+ _op = g()->nodes()->template create<Op>();
{
_op->x(input());
_op->y(_y);
@@ -1315,7 +1342,7 @@ public:
TypedTestGraph::init(T, {32}, {32});
_const = create_dummy_const<T>(g(), {32});
- _mul = g()->nodes()->create<luci::CircleMul>();
+ _mul = g()->nodes()->template create<luci::CircleMul>();
{
_mul->x(input());
_mul->y(_const);
@@ -1370,7 +1397,7 @@ public:
TypedTestGraph::init(T, {32}, {32});
_const = create_dummy_const<T>(g(), {32});
- _add = g()->nodes()->create<luci::CircleAdd>();
+ _add = g()->nodes()->template create<luci::CircleAdd>();
{
_add->x(input());
_add->y(_const);
@@ -1786,6 +1813,34 @@ TEST(QuantizedModelVerifierTest, StridedSlice_wrong_granularity_NEG)
SUCCEED();
}
+TEST(QuantizedModelVerifierTest, Sum)
+{
+ TEST_WITH_GRAPH(SumTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(SumTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(SumTestGraph, Type::S16, Granularity::ChannelWise);
+
+ TEST_WITH_LAYER_INFO(SumTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_LAYER_INFO(SumTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_LAYER_INFO(SumTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Sum_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(SumTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(SumTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(SumTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Sum_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY(SumTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_WRONG_GRANULARITY(SumTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_WRONG_GRANULARITY(SumTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
TEST(QuantizedModelVerifierTest, ArgMax)
{
TEST_WITH_GRAPH(ArgMaxTestGraph<Type::S32>, Type::U8, Granularity::LayerWise);
diff --git a/compiler/luci/pass/src/ReplaceNonConstFCWithBatchMatMulPass.test.cpp b/compiler/luci/pass/src/ReplaceNonConstFCWithBatchMatMulPass.test.cpp
index 93024f3f7..194893f01 100644
--- a/compiler/luci/pass/src/ReplaceNonConstFCWithBatchMatMulPass.test.cpp
+++ b/compiler/luci/pass/src/ReplaceNonConstFCWithBatchMatMulPass.test.cpp
@@ -16,6 +16,8 @@
#include "luci/Pass/ReplaceNonConstFCWithBatchMatMulPass.h"
+#include "helpers/CreateCircleConst.h"
+
#include <luci/test/TestIOGraph.h>
#include <luci/IR/CircleNodes.h>
@@ -26,52 +28,6 @@ namespace
using namespace luci::test;
-// TODO Reduce duplicate codes in ResolveCustomOpMatMulPass.cpp
-template <typename T>
-luci::CircleConst *create_const_node(loco::Graph *g, const loco::DataType dtype,
- const std::vector<uint32_t> &shape,
- const std::vector<T> &values)
-{
- auto node = g->nodes()->create<luci::CircleConst>();
- node->dtype(dtype);
- node->rank(shape.size());
-
- uint32_t size = 1;
- for (uint32_t i = 0; i < shape.size(); ++i)
- {
- node->dim(i) = shape.at(i);
- size *= shape.at(i);
- }
- node->shape_status(luci::ShapeStatus::VALID);
-
-#define INIT_VALUES(DT) \
- { \
- node->size<DT>(size); \
- for (uint32_t i = 0; i < values.size(); ++i) \
- node->at<DT>(i) = values[i]; \
- }
-
- switch (dtype)
- {
- case loco::DataType::U8:
- INIT_VALUES(loco::DataType::U8);
- break;
- case loco::DataType::S16:
- INIT_VALUES(loco::DataType::S16);
- break;
- case loco::DataType::S32:
- INIT_VALUES(loco::DataType::S32);
- break;
- case loco::DataType::FLOAT32:
- INIT_VALUES(loco::DataType::FLOAT32)
- break;
- default:
- INTERNAL_EXN("create_const_node called with unsupported type");
- break;
- }
- return node;
-}
-
/**
* Simple graph for test
*
@@ -104,7 +60,7 @@ public:
_tr_y = g->nodes()->create<luci::CircleTranspose>();
_tr_y->a(_y);
std::vector<int32_t> tr_val = {1, 0};
- _tr_y->perm(create_const_node(g, loco::DataType::S32, {2}, tr_val));
+ _tr_y->perm(luci::create_const_node(g, loco::DataType::S32, {2}, tr_val));
_fc = g->nodes()->create<luci::CircleFullyConnected>();
_fc->input(_x);
@@ -114,7 +70,7 @@ public:
_fc->shape(r_shape);
auto l = _fc->dim(_fc->rank() - 1).value();
std::vector<float> bias_val(l, bv);
- _fc->bias(create_const_node(g, loco::DataType::FLOAT32, {l}, bias_val));
+ _fc->bias(luci::create_const_node(g, loco::DataType::FLOAT32, {l}, bias_val));
_fc->name("fc");
}
diff --git a/compiler/luci/pass/src/ReplaceSubWithAddPass.cpp b/compiler/luci/pass/src/ReplaceSubWithAddPass.cpp
index 6bd83f5c5..f9102d836 100644
--- a/compiler/luci/pass/src/ReplaceSubWithAddPass.cpp
+++ b/compiler/luci/pass/src/ReplaceSubWithAddPass.cpp
@@ -17,6 +17,7 @@
#include "luci/Pass/ReplaceSubWithAddPass.h"
#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
#include <luci/Service/Nodes/CircleConst.h>
namespace
@@ -47,6 +48,7 @@ bool replace_sub_with_const_rhs(luci::CircleSub *sub)
add->y(neg_const_rhs);
add->name(sub->name());
add->fusedActivationFunction(sub->fusedActivationFunction());
+ luci::add_origin(add, luci::get_origin(sub));
loco::replace(sub).with(add);
return true;
}
diff --git a/compiler/luci/pass/src/RequantizePass.cpp b/compiler/luci/pass/src/RequantizePass.cpp
index a56536251..77c55324a 100644
--- a/compiler/luci/pass/src/RequantizePass.cpp
+++ b/compiler/luci/pass/src/RequantizePass.cpp
@@ -32,37 +32,9 @@ namespace luci
namespace
{
-// Check if the node is the bias of Conv2D, DepthwiseConv2D, or FullyConnected layer
-bool is_bias(CircleConst *node)
-{
- if (node == nullptr)
- return false;
-
- auto succs = loco::succs(node);
- if (succs.size() != 1) // assume bias is used by only one node
- return false;
-
- for (auto out : succs)
- {
- auto conv = dynamic_cast<CircleConv2D *>(out);
- if (conv != nullptr && conv->bias() == node)
- return true;
-
- auto dw_conv = dynamic_cast<CircleDepthwiseConv2D *>(out);
- if (dw_conv != nullptr && dw_conv->bias() == node)
- return true;
-
- auto fc = dynamic_cast<CircleFullyConnected *>(out);
- if (fc != nullptr && fc->bias() == node)
- return true;
-
- auto tconv = dynamic_cast<CircleTransposeConv *>(out);
- if (tconv != nullptr && tconv->bias() == node)
- return true;
- }
- return false;
-}
-
+// Requantize Non-const node from int8 to uint8
+// Original values: -128 ~ 127
+// After requantization: 0 ~ 255
void requant_nonconst_int8_to_uint8(CircleNode *circle_node)
{
assert(circle_node->dtype() == loco::DataType::S8);
@@ -107,99 +79,48 @@ void requant_const_int8_to_uint8(CircleConst *node)
}
}
+#define RETURN_UNLESS(cond) \
+ if (not(cond)) \
+ return;
+
/**
- * @brief RequantizeNonConst requantizes tensors for activations
+ * @brief Requantize int8 quantized tensors to uint8 tensors
*/
-struct RequantizeNonConst final : public luci::CircleNodeMutableVisitor<bool>
+struct RequantizeS8ToU8 final : public luci::CircleNodeMutableVisitor<void>
{
- RequantizeNonConst(loco::DataType input, loco::DataType output)
- : _input_type(input), _output_type(output)
- {
- }
-
- loco::DataType _input_type;
- loco::DataType _output_type;
-
- // Requantize input tensors of each node
- bool visit(luci::CircleNode *node)
+ // Requantize non-const tensors
+ void visit(luci::CircleNode *node)
{
LOGGER(l);
- INFO(l) << "RequantizeNonConst visit node: " << node->name() << std::endl;
- auto arity = node->arity();
- for (uint32_t i = 0; i < arity; i++)
- {
- auto input_node = node->arg(i);
- auto circle_node = loco::must_cast<luci::CircleNode *>(input_node);
+ INFO(l) << "RequantizeS8ToU8 visit non-const node: " << node->name() << std::endl;
- // Check if this was quantized (only quantized tensors are requantized)
- if (circle_node->quantparam() == nullptr)
- continue;
+ // Ignore non-quantized tensors
+ RETURN_UNLESS(node->quantparam() != nullptr);
- // Check if this is already requantized
- if (circle_node->dtype() == _output_type)
- continue;
+ // Check dtype is int8
+ RETURN_UNLESS(node->dtype() == loco::DataType::S8);
- // Check if this is not const (only non-const is requantized in this function)
- auto circle_const = dynamic_cast<CircleConst *>(circle_node);
- if (circle_const != nullptr)
- continue;
-
- if (_input_type == loco::DataType::S8 && _output_type == loco::DataType::U8)
- requant_nonconst_int8_to_uint8(circle_node);
- }
- return false;
- }
-};
-
-/**
- * @brief RequantizeConst requantizes tensors for weights
- */
-struct RequantizeConst final : public luci::CircleNodeMutableVisitor<bool>
-{
- RequantizeConst(loco::DataType input, loco::DataType output)
- : _input_type(input), _output_type(output)
- {
+ requant_nonconst_int8_to_uint8(node);
}
- loco::DataType _input_type;
- loco::DataType _output_type;
-
- // Requantize input tensors of each node
- bool visit(luci::CircleNode *node)
+ // Requantize const tensors
+ void visit(luci::CircleConst *node)
{
LOGGER(l);
- INFO(l) << "RequantizeConst visit node: " << node->name() << std::endl;
- auto arity = node->arity();
- for (uint32_t i = 0; i < arity; i++)
- {
- auto input_node = node->arg(i);
- auto circle_node = loco::must_cast<luci::CircleNode *>(input_node);
+ INFO(l) << "RequantizeS8ToU8 visit const node: " << node->name() << std::endl;
- // Check if this was quantized (only quantized tensors are requantized)
- if (circle_node->quantparam() == nullptr)
- continue;
+ // Ignore non-quantized tensors
+ RETURN_UNLESS(node->quantparam() != nullptr);
- // Check if this is already requantized
- if (circle_node->dtype() == _output_type)
- continue;
+ // Check dtype is int8
+ RETURN_UNLESS(node->dtype() == loco::DataType::S8);
- // Check if this is const (only const is requantized in this function)
- auto circle_const = dynamic_cast<CircleConst *>(circle_node);
- if (circle_const == nullptr)
- continue;
-
- // Check if this is not bias
- // bias is not requantized when int8 -> uint8
- if (is_bias(circle_const))
- continue;
-
- if (_input_type == loco::DataType::S8 && _output_type == loco::DataType::U8)
- requant_const_int8_to_uint8(circle_const);
- }
- return false;
+ requant_const_int8_to_uint8(node);
}
};
+#undef RETURN_UNLESS
+
} // namespace
bool RequantizePass::run(loco::Graph *g)
@@ -207,20 +128,21 @@ bool RequantizePass::run(loco::Graph *g)
LOGGER(l);
INFO(l) << "RequantizePass Start" << std::endl;
- // Requantize non-const (activations)
- for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ // Input: int8 model
+ // Output: uint8 model
+ if (_input_dtype == loco::DataType::S8 and _output_dtype == loco::DataType::U8)
{
- RequantizeNonConst rqnc(_input_dtype, _output_dtype);
- auto circle_node = loco::must_cast<luci::CircleNode *>(node);
- circle_node->accept(&rqnc);
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ RequantizeS8ToU8 rq;
+ auto circle_node = loco::must_cast<luci::CircleNode *>(node);
+ circle_node->accept(&rq);
+ }
}
-
- // Requantize const (including weights, constants)
- for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ else
{
- RequantizeConst rqc(_input_dtype, _output_dtype);
- auto circle_node = loco::must_cast<luci::CircleNode *>(node);
- circle_node->accept(&rqc);
+ // Ignore other cases
+ return false;
}
// Update output dtype
@@ -228,7 +150,8 @@ bool RequantizePass::run(loco::Graph *g)
for (auto node : loco::output_nodes(g))
{
auto circle_node = loco::must_cast<luci::CircleOutput *>(node);
- if (static_cast<luci::CircleNode *>(circle_node->from())->dtype() == _output_dtype)
+ auto from_node = loco::must_cast<luci::CircleNode *>(circle_node->from());
+ if (from_node->dtype() == _output_dtype)
{
circle_node->dtype(_output_dtype);
auto graph_output = graph_outputs->at(circle_node->index());
diff --git a/compiler/luci/pass/src/RequantizePass.test.cpp b/compiler/luci/pass/src/RequantizePass.test.cpp
index d26743c9d..a9293ce27 100644
--- a/compiler/luci/pass/src/RequantizePass.test.cpp
+++ b/compiler/luci/pass/src/RequantizePass.test.cpp
@@ -16,11 +16,167 @@
#include "luci/Pass/RequantizePass.h"
+#include "helpers/CreateCircleConst.h"
+
+#include <luci/test/TestIOGraph.h>
+#include <luci/IR/CircleNodes.h>
+#include <luci/IR/CircleQuantParam.h>
+
+#include <vector>
+
#include <gtest/gtest.h>
+using namespace luci;
+using namespace luci::test;
+
+namespace
+{
+
+/**
+ * Simple graph for test
+ *
+ * BEFORE
+ *
+ * [IFM (S8)] [W (S8)] [B (S32)]
+ * | | |
+ * +-------+--------+
+ * |
+ * V
+ * [FC]
+ * |
+ * V
+ * [OFM(S8)]
+ *
+ * AFTER
+ *
+ * [IFM (U8)] [W (U8)] [B (S32)]
+ * | | |
+ * +-------+--------+
+ * |
+ * V
+ * [FC]
+ * |
+ * V
+ * [OFM(U8)]
+ */
+struct S8FCGraphlet
+{
+public:
+ S8FCGraphlet() = default;
+ virtual ~S8FCGraphlet() = default;
+
+ void init(loco::Graph *g, const ShapeU32 out_shape, const ShapeU32 w_shape,
+ const ShapeU32 bias_shape)
+ {
+ _fc = g->nodes()->create<CircleFullyConnected>();
+ _fc->input(_x);
+ _x->dtype(loco::DataType::S8);
+ {
+ auto quantparam = std::make_unique<CircleQuantParam>();
+ quantparam->scale.push_back(1.0);
+ quantparam->zerop.push_back(0);
+ quantparam->quantized_dimension = 0;
+ _x->quantparam(std::move(quantparam));
+ }
+
+ _weights = create_const_node<int8_t>(g, loco::DataType::S8, w_shape, 1.0);
+ {
+ auto w_qparam = std::make_unique<CircleQuantParam>();
+ std::vector<float> w_scale(_weights->dim(0).value(), 1.0);
+ std::vector<int64_t> w_zp(_weights->dim(0).value(), 0);
+ w_qparam->scale = w_scale;
+ w_qparam->zerop = w_zp;
+ w_qparam->quantized_dimension = 0;
+ _weights->quantparam(std::move(w_qparam));
+ }
+ _fc->weights(_weights);
+
+ _bias = create_const_node<int32_t>(g, loco::DataType::S32, bias_shape, 1.0);
+ {
+ auto b_qparam = std::make_unique<CircleQuantParam>();
+ const auto bias_size = _bias->size<loco::DataType::S32>();
+ std::vector<float> b_scale(bias_size, 1.0);
+ std::vector<int64_t> b_zp(bias_size, 0);
+ b_qparam->scale = b_scale;
+ b_qparam->zerop = b_zp;
+ b_qparam->quantized_dimension = 0;
+ _bias->quantparam(std::move(b_qparam));
+ }
+
+ _fc->fusedActivationFunction(luci::FusedActFunc::NONE);
+ _fc->dtype(loco::DataType::S8);
+ _fc->shape(out_shape);
+ _fc->bias(_bias);
+ _fc->name("fc");
+ {
+ auto quantparam = std::make_unique<CircleQuantParam>();
+ quantparam->scale.push_back(1.0);
+ quantparam->zerop.push_back(0);
+ quantparam->quantized_dimension = 0;
+ _fc->quantparam(std::move(quantparam));
+ }
+ }
+
+public:
+ CircleFullyConnected *_fc = nullptr;
+ CircleInput *_x = nullptr;
+ CircleConst *_weights = nullptr;
+ CircleConst *_bias = nullptr;
+};
+
+struct S8FCGraph final : public TestIGraphlet, public TestOGraphlet, public S8FCGraphlet
+{
+ void init(const ShapeU32 in_shape, const ShapeU32 w_shape, const ShapeU32 out_shape,
+ const ShapeU32 bias_shape)
+ {
+ TestIGraphlet::init(g(), in_shape);
+ TestOGraphlet::init(g(), out_shape);
+ _x = input();
+ S8FCGraphlet::init(g(), out_shape, w_shape, bias_shape);
+ output()->from(_fc);
+ }
+};
+
+class RequantizeS8ToU8FCTest : public ::testing::Test
+{
+public:
+ S8FCGraph g;
+};
+
+} // namespace
+
TEST(RequantizePassTest, name)
{
luci::RequantizePass pass(loco::DataType::FLOAT32, loco::DataType::U8);
auto const name = pass.name();
ASSERT_NE(nullptr, name);
}
+
+TEST_F(RequantizeS8ToU8FCTest, FC)
+{
+ g.init({1, 18, 80} /* ifm shape */, {256, 80} /* weights shape*/, {18, 256} /* ofm shape */,
+ {1, 256} /* bias shape*/);
+
+ luci::RequantizePass rq(loco::DataType::S8, loco::DataType::U8);
+ rq.run(g.g());
+
+ EXPECT_EQ(loco::DataType::U8, g._x->dtype());
+ EXPECT_EQ(loco::DataType::U8, g._fc->dtype());
+ EXPECT_EQ(loco::DataType::U8, g._weights->dtype());
+ EXPECT_EQ(loco::DataType::S32, g._bias->dtype());
+}
+
+TEST_F(RequantizeS8ToU8FCTest, FC_wrong_dtype_NEG)
+{
+ g.init({1, 18, 80} /* ifm shape */, {256, 80} /* weights shape*/, {18, 256} /* ofm shape */,
+ {1, 256} /* bias shape*/);
+
+ // Wrong dtype
+ luci::RequantizePass rq(loco::DataType::U8, loco::DataType::S8);
+ rq.run(g.g());
+
+ EXPECT_EQ(loco::DataType::S8, g._x->dtype());
+ EXPECT_EQ(loco::DataType::S8, g._fc->dtype());
+ EXPECT_EQ(loco::DataType::S8, g._weights->dtype());
+ EXPECT_EQ(loco::DataType::S32, g._bias->dtype());
+}
diff --git a/compiler/luci/pass/src/ResolveCustomOpMatMulPass.cpp b/compiler/luci/pass/src/ResolveCustomOpMatMulPass.cpp
index f61882796..add55f66c 100644
--- a/compiler/luci/pass/src/ResolveCustomOpMatMulPass.cpp
+++ b/compiler/luci/pass/src/ResolveCustomOpMatMulPass.cpp
@@ -16,6 +16,8 @@
#include "luci/Pass/ResolveCustomOpMatMulPass.h"
+#include "helpers/CreateCircleConst.h"
+
#include <loco/IR/DataTypeTraits.h>
#include <luci/IR/CircleNodes.h>
@@ -29,51 +31,6 @@
namespace
{
-template <typename T>
-luci::CircleConst *create_const_node(loco::Graph *g, const loco::DataType dtype,
- const std::vector<uint32_t> &shape,
- const std::vector<T> &values)
-{
- auto node = g->nodes()->create<luci::CircleConst>();
- node->dtype(dtype);
- node->rank(shape.size());
-
- uint32_t size = 1;
- for (uint32_t i = 0; i < shape.size(); ++i)
- {
- node->dim(i) = shape.at(i);
- size *= shape.at(i);
- }
- node->shape_status(luci::ShapeStatus::VALID);
-
-#define INIT_VALUES(DT) \
- { \
- node->size<DT>(size); \
- for (uint32_t i = 0; i < values.size(); ++i) \
- node->at<DT>(i) = values[i]; \
- }
-
- switch (dtype)
- {
- case loco::DataType::U8:
- INIT_VALUES(loco::DataType::U8);
- break;
- case loco::DataType::S16:
- INIT_VALUES(loco::DataType::S16);
- break;
- case loco::DataType::S32:
- INIT_VALUES(loco::DataType::S32);
- break;
- case loco::DataType::FLOAT32:
- INIT_VALUES(loco::DataType::FLOAT32)
- break;
- default:
- INTERNAL_EXN("create_const_node called with unsupported type");
- break;
- }
- return node;
-}
-
bool resolve_matmul(luci::CircleCustom *cop)
{
#define CHECK_OR_FALSE(condition) \
@@ -121,11 +78,12 @@ bool resolve_matmul(luci::CircleCustom *cop)
if (transpose_a)
{
// Create a permutation constant node
- std::vector<uint32_t> perm;
- for (uint32_t i = 0; i < circle_lhs->rank(); ++i)
+ std::vector<int32_t> perm;
+ const auto lhs_rank = static_cast<int32_t>(circle_lhs->rank());
+ for (int32_t i = 0; i < lhs_rank; ++i)
perm.push_back(i);
std::swap(perm[circle_lhs->rank() - 1], perm[circle_lhs->rank() - 2]);
- auto perm_node = create_const_node(graph, S32, {circle_lhs->rank()}, perm);
+ auto perm_node = luci::create_const_node(graph, S32, {circle_lhs->rank()}, perm);
perm_node->name(name + "/lhs/Transpose/perm");
// Now make a transpose node
auto transpose_node = graph->nodes()->create<luci::CircleTranspose>();
@@ -141,8 +99,8 @@ bool resolve_matmul(luci::CircleCustom *cop)
// in row-major order, thus we need to convert between them.
if (!transpose_b)
{
- const std::vector<uint32_t> perm{1, 0};
- auto perm_node = create_const_node(graph, S32, {2}, perm);
+ const std::vector<int32_t> perm{1, 0};
+ auto perm_node = luci::create_const_node(graph, S32, {2}, perm);
perm_node->name(name + "/rhs/Transpose/perm");
auto transpose_node = graph->nodes()->create<luci::CircleTranspose>();
transpose_node->a(rhs);
diff --git a/compiler/luci/pass/src/SubstituteSplitVToSplitPass.test.cpp b/compiler/luci/pass/src/SubstituteSplitVToSplitPass.test.cpp
index 6e30103f9..43f9cc116 100644
--- a/compiler/luci/pass/src/SubstituteSplitVToSplitPass.test.cpp
+++ b/compiler/luci/pass/src/SubstituteSplitVToSplitPass.test.cpp
@@ -16,6 +16,8 @@
#include "luci/Pass/SubstituteSplitVToSplitPass.h"
+#include "helpers/CreateCircleConst.h"
+
#include <luci/test/TestIOGraph.h>
#include <gtest/gtest.h>
@@ -30,51 +32,6 @@ const int C = 32;
const int H = 8;
const int W = 8;
-// Reduce duplicate codes in ResolveCustomOpMatMulPass.cpp
-template <typename T>
-luci::CircleConst *create_const_node(loco::Graph *g, const loco::DataType dtype,
- const std::vector<uint32_t> &shape,
- const std::vector<T> &values)
-{
- auto node = g->nodes()->create<luci::CircleConst>();
- node->dtype(dtype);
- node->rank(shape.size());
-
- uint32_t size = 1;
- for (uint32_t i = 0; i < shape.size(); ++i)
- {
- node->dim(i) = shape.at(i);
- size *= shape.at(i);
- }
- node->shape_status(luci::ShapeStatus::VALID);
-
-#define INIT_VALUES(DT) \
- { \
- node->size<DT>(size); \
- for (uint32_t i = 0; i < values.size(); ++i) \
- node->at<DT>(i) = values[i]; \
- }
-
- switch (dtype)
- {
- case loco::DataType::U8:
- INIT_VALUES(loco::DataType::U8);
- break;
- case loco::DataType::S16:
- INIT_VALUES(loco::DataType::S16);
- break;
- case loco::DataType::S32:
- INIT_VALUES(loco::DataType::S32);
- break;
- case loco::DataType::FLOAT32:
- INIT_VALUES(loco::DataType::FLOAT32)
- break;
- default:
- INTERNAL_EXN("create_const_node called with unsupported type");
- break;
- }
- return node;
-}
/**
* graph having SplitV operator
*
@@ -95,10 +52,10 @@ public:
void init(loco::Graph *g)
{
const std::vector<int32_t> splits{16, 16};
- auto size_splits = create_const_node(g, loco::DataType::S32, {2}, splits);
+ auto size_splits = luci::create_const_node(g, loco::DataType::S32, {2}, splits);
const std::vector<int32_t> dim{3};
- auto split_dim = create_const_node(g, loco::DataType::S32, {1}, dim);
+ auto split_dim = luci::create_const_node(g, loco::DataType::S32, {1}, dim);
_sv = g->nodes()->create<luci::CircleSplitV>();
_sv->size_splits(size_splits);
diff --git a/compiler/luci/pass/src/VerifyQuantizedBiasScale.cpp b/compiler/luci/pass/src/VerifyQuantizedBiasScale.cpp
index e65d576cd..d40c19b9b 100644
--- a/compiler/luci/pass/src/VerifyQuantizedBiasScale.cpp
+++ b/compiler/luci/pass/src/VerifyQuantizedBiasScale.cpp
@@ -31,7 +31,7 @@ namespace
bool same(float a, float b)
{
constexpr float epsilon = 1e-10;
- return abs(a - b) < epsilon;
+ return std::abs(a - b) < epsilon;
}
// Check bias scale = input scale * weight scale
diff --git a/compiler/luci/pass/src/VerifyQuantizedNodeGranularity.h b/compiler/luci/pass/src/VerifyQuantizedNodeGranularity.h
index 6bf7ff698..cc618bf0e 100644
--- a/compiler/luci/pass/src/VerifyQuantizedNodeGranularity.h
+++ b/compiler/luci/pass/src/VerifyQuantizedNodeGranularity.h
@@ -298,6 +298,13 @@ private:
return true;
}
+ bool visit(const luci::CircleSum *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->input()));
+ return true;
+ }
+
bool visit(const luci::CircleArgMax *node)
{
// node's output is index, thus not quantized
@@ -333,6 +340,13 @@ private:
return true;
}
+ bool visit(const luci::CircleGelu *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->features()));
+ return true;
+ }
+
bool visit(const luci::CircleGreater *node)
{
RETURN_FALSE_UNLESS(is_lwq(node->x()));
diff --git a/compiler/luci/pass/src/VerifyQuantizedNodeType.cpp b/compiler/luci/pass/src/VerifyQuantizedNodeType.cpp
index 3ce32555b..4bad9522b 100644
--- a/compiler/luci/pass/src/VerifyQuantizedNodeType.cpp
+++ b/compiler/luci/pass/src/VerifyQuantizedNodeType.cpp
@@ -181,6 +181,12 @@ bool VerifyQuantizedNodeTypeBase<Qtype, Btype>::visit(const luci::CircleFullyCon
}
template <loco::DataType Qtype, loco::DataType Btype>
+bool VerifyQuantizedNodeTypeBase<Qtype, Btype>::visit(const luci::CircleGelu *node)
+{
+ return group_has_type(node, Qtype);
+}
+
+template <loco::DataType Qtype, loco::DataType Btype>
bool VerifyQuantizedNodeTypeBase<Qtype, Btype>::visit(const luci::CircleGreater *node)
{
RETURN_FALSE_UNLESS(has_type(node, loco::DataType::BOOL))
@@ -454,6 +460,15 @@ bool VerifyQuantizedNodeTypeBase<Qtype, Btype>::visit(const luci::CircleStridedS
}
template <loco::DataType Qtype, loco::DataType Btype>
+bool VerifyQuantizedNodeTypeBase<Qtype, Btype>::visit(const luci::CircleSum *node)
+{
+ RETURN_FALSE_UNLESS(has_type(node, Qtype))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Qtype))
+ RETURN_FALSE_UNLESS(has_type(node->reduction_indices(), loco::DataType::S32))
+ return true;
+}
+
+template <loco::DataType Qtype, loco::DataType Btype>
bool VerifyQuantizedNodeTypeBase<Qtype, Btype>::visit(const luci::CircleTranspose *node)
{
RETURN_FALSE_UNLESS(has_type(node, Qtype))
diff --git a/compiler/luci/pass/src/VerifyQuantizedNodeType.h b/compiler/luci/pass/src/VerifyQuantizedNodeType.h
index 789d3c7cd..03f1e1d86 100644
--- a/compiler/luci/pass/src/VerifyQuantizedNodeType.h
+++ b/compiler/luci/pass/src/VerifyQuantizedNodeType.h
@@ -88,6 +88,7 @@ private:
bool visit(const luci::CircleFloor *node);
bool visit(const luci::CircleFloorDiv *node);
bool visit(const luci::CircleFullyConnected *node);
+ bool visit(const luci::CircleGelu *node);
bool visit(const luci::CircleGreater *node);
bool visit(const luci::CircleGreaterEqual *node);
bool visit(const luci::CircleInstanceNorm *node);
@@ -119,6 +120,7 @@ private:
bool visit(const luci::CircleSplitVOut *node);
bool visit(const luci::CircleSqrt *node);
bool visit(const luci::CircleStridedSlice *node);
+ bool visit(const luci::CircleSum *node);
bool visit(const luci::CircleTranspose *node);
bool visit(const luci::CircleTransposeConv *node);
bool visit(const luci::CircleUnpack *node);
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALFill.h b/compiler/luci/pass/src/helpers/CreateCircleConst.cpp
index c9eb33b4d..bf1b0baf7 100644
--- a/onert-micro/luci-interpreter/pal/cmsisnn/PALFill.h
+++ b/compiler/luci/pass/src/helpers/CreateCircleConst.cpp
@@ -1,6 +1,5 @@
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,9 +14,7 @@
* limitations under the License.
*/
-#ifndef LUCI_INTERPRETER_PAL_FILL_H
-#define LUCI_INTERPRETER_PAL_FILL_H
+#include "CreateCircleConst.h"
-#include "PALreference_ops.h"
-
-#endif // LUCI_INTERPRETER_PAL_FILL_H
+// NOTE Do NOT delete this file; this file enforces compiler to check whether 'CreateCircleConst.h'
+// is complete.
diff --git a/compiler/luci/pass/src/helpers/CreateCircleConst.h b/compiler/luci/pass/src/helpers/CreateCircleConst.h
new file mode 100644
index 000000000..89c1a47be
--- /dev/null
+++ b/compiler/luci/pass/src/helpers/CreateCircleConst.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_PASS_HELPERS_CREATE_CIRCLE_CONST_H__
+#define __LUCI_PASS_HELPERS_CREATE_CIRCLE_CONST_H__
+
+#include <luci/IR/CircleNodes.h>
+
+#include "TypeMapper.h"
+
+#include <vector>
+
+namespace luci
+{
+
+// Create CircleConst filled with a single value
+// Never return nullptr
+// TODO Remove dtype from the argument
+template <typename T>
+CircleConst *create_const_node(loco::Graph *g, const loco::DataType dtype,
+ const std::vector<uint32_t> &shape, const T value)
+{
+ auto node = g->nodes()->create<CircleConst>();
+ node->dtype(dtype);
+ node->rank(shape.size());
+
+ uint32_t size = 1;
+ for (uint32_t i = 0; i < shape.size(); ++i)
+ {
+ node->dim(i) = shape.at(i);
+ size *= shape.at(i);
+ }
+ node->shape_status(ShapeStatus::VALID);
+
+ node->size<TypeMapper<T>::get()>(size);
+ for (uint32_t i = 0; i < size; i++)
+ {
+ node->at<TypeMapper<T>::get()>(i) = value;
+ }
+
+ return node;
+}
+
+// Create CircleConst filled with values
+// Never return nullptr
+// TODO Remove dtype from the argument
+template <typename T>
+luci::CircleConst *create_const_node(loco::Graph *g, const loco::DataType dtype,
+ const std::vector<uint32_t> &shape,
+ const std::vector<T> &values)
+{
+ auto node = g->nodes()->create<luci::CircleConst>();
+ node->dtype(dtype);
+ node->rank(shape.size());
+
+ uint32_t size = 1;
+ for (uint32_t i = 0; i < shape.size(); ++i)
+ {
+ node->dim(i) = shape.at(i);
+ size *= shape.at(i);
+ }
+ node->shape_status(luci::ShapeStatus::VALID);
+
+ node->size<TypeMapper<T>::get()>(size);
+ for (uint32_t i = 0; i < size; i++)
+ {
+ node->at<TypeMapper<T>::get()>(i) = values[i];
+ }
+
+ return node;
+}
+
+} // namespace luci
+
+#endif // __LUCI_PASS_HELPERS_CREATE_CIRCLE_CONST_H__
diff --git a/compiler/luci/pass/src/helpers/TypeMapper.h b/compiler/luci/pass/src/helpers/TypeMapper.h
index 90760e95b..a3e27d259 100644
--- a/compiler/luci/pass/src/helpers/TypeMapper.h
+++ b/compiler/luci/pass/src/helpers/TypeMapper.h
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+#ifndef __LUCI_PASS_HELPERS_TYPE_MAPPER_H__
+#define __LUCI_PASS_HELPERS_TYPE_MAPPER_H__
+
#include <loco/IR/DataType.h>
#include <cstdint>
@@ -75,3 +78,5 @@ template <> struct TypeMapper<int64_t>
};
} // namespace luci
+
+#endif // __LUCI_PASS_HELPERS_TYPE_MAPPER_H__
diff --git a/compiler/luci/requires.cmake b/compiler/luci/requires.cmake
index f3546b05a..a71d4482c 100644
--- a/compiler/luci/requires.cmake
+++ b/compiler/luci/requires.cmake
@@ -4,7 +4,7 @@ require("loco")
require("locop")
require("logo")
require("logo-core")
-require("mio-circle04")
+require("mio-circle06")
require("luci-compute")
require("oops")
require("hermes")
diff --git a/compiler/luci/service/include/luci/Service/CircleShapeInference.h b/compiler/luci/service/include/luci/Service/CircleShapeInference.h
index 2c1120941..92c5fb04c 100644
--- a/compiler/luci/service/include/luci/Service/CircleShapeInference.h
+++ b/compiler/luci/service/include/luci/Service/CircleShapeInference.h
@@ -79,6 +79,7 @@ public:
// loco::TensorShape visit(const luci::CircleGatherNd *node) final;
// loco::TensorShape visit(const luci::CircleGreater *node) final;
// loco::TensorShape visit(const luci::CircleGreaterEqual *node) final;
+ // loco::TensorShape visit(const luci::CircleHardSwish *node) final;
// loco::TensorShape visit(const luci::CircleIf *node) final;
// loco::TensorShape visit(const luci::CircleL2Normalize *node) final;
// loco::TensorShape visit(const luci::CircleL2Pool2D *node) final;
diff --git a/compiler/luci/service/include/luci/Service/CircleTypeInference.h b/compiler/luci/service/include/luci/Service/CircleTypeInference.h
index e0ceabeac..4f4ab0f34 100644
--- a/compiler/luci/service/include/luci/Service/CircleTypeInference.h
+++ b/compiler/luci/service/include/luci/Service/CircleTypeInference.h
@@ -78,6 +78,7 @@ public:
// loco::DataType visit(const luci::CircleGatherNd *node) final;
// loco::DataType visit(const luci::CircleGreater *node) final;
// loco::DataType visit(const luci::CircleGreaterEqual *node) final;
+ // loco::DataType visit(const luci::CircleHardSwish *node) final;
// loco::DataType visit(const luci::CircleIf *node) final;
// loco::DataType visit(const luci::CircleL2Normalize *node) final;
// loco::DataType visit(const luci::CircleL2Pool2D *node) final;
diff --git a/compiler/luci/service/include/luci/Service/Validate.h b/compiler/luci/service/include/luci/Service/Validate.h
index c6a2b0e0d..815e5e380 100644
--- a/compiler/luci/service/include/luci/Service/Validate.h
+++ b/compiler/luci/service/include/luci/Service/Validate.h
@@ -39,6 +39,10 @@ bool validate_unique_name(luci::Module *);
bool validate(luci::Module *);
+bool validate_shape(loco::Graph *);
+
+bool validate_shape(luci::Module *);
+
} // namespace luci
#endif // __LUCI_SERVICE_VALIDATE_H__
diff --git a/compiler/luci/service/src/CircleCloneNode.h b/compiler/luci/service/src/CircleCloneNode.h
index 95f06db4c..e0b4dbc41 100644
--- a/compiler/luci/service/src/CircleCloneNode.h
+++ b/compiler/luci/service/src/CircleCloneNode.h
@@ -102,8 +102,10 @@ public:
public:
luci::CircleNode *visit(const luci::CircleGather *) final;
luci::CircleNode *visit(const luci::CircleGatherNd *) final;
+ luci::CircleNode *visit(const luci::CircleGelu *) final;
luci::CircleNode *visit(const luci::CircleGreater *) final;
luci::CircleNode *visit(const luci::CircleGreaterEqual *) final;
+ luci::CircleNode *visit(const luci::CircleHardSwish *) final;
luci::CircleNode *visit(const luci::CircleIf *) final;
luci::CircleNode *visit(const luci::CircleNode *) final { return nullptr; }
diff --git a/compiler/luci/service/src/CircleShapeInferenceRule.cpp b/compiler/luci/service/src/CircleShapeInferenceRule.cpp
index 9d4dbab16..d56886c97 100644
--- a/compiler/luci/service/src/CircleShapeInferenceRule.cpp
+++ b/compiler/luci/service/src/CircleShapeInferenceRule.cpp
@@ -284,7 +284,7 @@ template <class CIRCLENODE> loco::NodeShape infer_arg_maxmin(const CIRCLENODE *n
assert(select_axis < input_shape.rank());
if (select_axis < 0)
- select_axis += input_shape.rank();
+ select_axis += static_cast<int64_t>(input_shape.rank());
// NOTE select_axis is removed
loco::TensorShape shape_output;
@@ -1287,7 +1287,7 @@ loco::NodeShape infer_slice(const luci::CircleSlice *node)
auto size = vect_size.at(idx);
if (size == -1)
{
- size = input_shape.dim(idx).value() - vect_begin.at(idx);
+ size = static_cast<int64_t>(input_shape.dim(idx).value()) - vect_begin.at(idx);
}
output_shape.dim(idx) = size;
}
@@ -1874,7 +1874,7 @@ loco::NodeShape infer_split_v_out(const luci::CircleSplitVOut *node)
assert(0 <= index_this && index_this < split->num_split());
auto split_depth = size_splits->at<S32>(index_this);
if (split_depth == -1)
- split_depth = input_size - size_splits_sum;
+ split_depth = static_cast<int32_t>(input_size) - static_cast<int32_t>(size_splits_sum);
loco::TensorShape output_shape = split_shape;
@@ -2087,10 +2087,24 @@ public:
loco::NodeShape visit(const luci::CircleGatherNd *node) final { return infer_gather_nd(node); }
+ loco::NodeShape visit(const luci::CircleGelu *node) final
+ {
+ auto input_shape = luci::shape_get(node->features()).as<loco::TensorShape>();
+
+ return loco::NodeShape{input_shape};
+ }
+
loco::NodeShape visit(const luci::CircleGreater *node) final { return broadcast_xy(node); }
loco::NodeShape visit(const luci::CircleGreaterEqual *node) final { return broadcast_xy(node); }
+ loco::NodeShape visit(const luci::CircleHardSwish *node) final
+ {
+ auto input_shape = luci::shape_get(node->features()).as<loco::TensorShape>();
+
+ return loco::NodeShape{input_shape};
+ }
+
loco::NodeShape visit(const luci::CircleIf *node) final
{
// Shape of CircleIf is not used. Just use input 0
diff --git a/compiler/luci/service/src/CircleTypeInferenceRule.cpp b/compiler/luci/service/src/CircleTypeInferenceRule.cpp
index 44c93305b..bd3feb977 100644
--- a/compiler/luci/service/src/CircleTypeInferenceRule.cpp
+++ b/compiler/luci/service/src/CircleTypeInferenceRule.cpp
@@ -172,10 +172,20 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
return luci::dtype_get(node->params());
}
+ loco::DataType visit(const luci::CircleGelu *node) final
+ {
+ return luci::dtype_get(node->features());
+ }
+
loco::DataType visit(const luci::CircleGreater *) final { return loco::DataType::BOOL; }
loco::DataType visit(const luci::CircleGreaterEqual *) final { return loco::DataType::BOOL; }
+ loco::DataType visit(const luci::CircleHardSwish *node) final
+ {
+ return luci::dtype_get(node->features());
+ }
+
loco::DataType visit(const luci::CircleIf *node) final
{
// Type of If is not used. Just use input 0
diff --git a/compiler/luci/service/src/Nodes/CircleGelu.cpp b/compiler/luci/service/src/Nodes/CircleGelu.cpp
new file mode 100644
index 000000000..62a0d4094
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleGelu.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNodeLet<CN::GHIJ>::visit(const luci::CircleGelu *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleGelu>();
+ if (cloned != nullptr)
+ cloned->approximate(node->approximate());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleGelu.test.cpp b/compiler/luci/service/src/Nodes/CircleGelu.test.cpp
new file mode 100644
index 000000000..a043b2a5d
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleGelu.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Gelu)
+{
+ auto g = loco::make_graph();
+ auto node_gelu = g->nodes()->create<luci::CircleGelu>();
+ node_gelu->approximate(false);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_gelu, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_gelu = dynamic_cast<luci::CircleGelu *>(cloned);
+ ASSERT_NE(nullptr, cloned_gelu);
+ ASSERT_EQ(node_gelu->approximate(), cloned_gelu->approximate());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleHardSwish.cpp b/compiler/luci/service/src/Nodes/CircleHardSwish.cpp
new file mode 100644
index 000000000..bbc466e3f
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleHardSwish.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNodeLet<CN::GHIJ>::visit(const luci::CircleHardSwish *)
+{
+ return _graph->nodes()->create<luci::CircleHardSwish>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleHardSwish.test.cpp b/compiler/luci/service/src/Nodes/CircleHardSwish.test.cpp
new file mode 100644
index 000000000..b79386bea
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleHardSwish.test.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Service/CircleShapeInference.h>
+#include <luci/Service/CircleTypeInference.h>
+
+#include <loco/IR/TensorShape.h>
+
+#include <gtest/gtest.h>
+
+TEST(ShapeRuleTest, simple_hardswish)
+{
+ luci::CircleInput input;
+ luci::CircleHardSwish hard_swish;
+
+ input.shape({3, 4});
+ input.shape_status(luci::ShapeStatus::VALID);
+
+ hard_swish.features(&input);
+
+ loco::TensorShape shape;
+ luci::sinf::Rule shape_inf_rule;
+
+ ASSERT_TRUE(shape_inf_rule.infer(&hard_swish, shape));
+ ASSERT_EQ(2, shape.rank());
+ ASSERT_EQ(3, shape.dim(0).value());
+ ASSERT_EQ(4, shape.dim(1).value());
+}
+
+TEST(DataTypeRuleTest, simple_hardswish)
+{
+ luci::CircleInput input;
+ luci::CircleHardSwish hard_swish;
+
+ input.dtype(loco::DataType::S32);
+
+ hard_swish.features(&input);
+
+ loco::DataType dtype;
+ luci::tinf::Rule type_inf_rule;
+
+ ASSERT_TRUE(type_inf_rule.infer(&hard_swish, dtype));
+ ASSERT_EQ(loco::DataType::S32, dtype);
+}
+
+TEST(CloneNodeTest, clone_HardSwish)
+{
+ auto g = loco::make_graph();
+ auto node_hardswish = g->nodes()->create<luci::CircleHardSwish>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_hardswish, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_hardswish = dynamic_cast<luci::CircleHardSwish *>(cloned);
+ ASSERT_NE(nullptr, cloned_hardswish);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleTransposeConv.cpp b/compiler/luci/service/src/Nodes/CircleTransposeConv.cpp
index 5d2fa482d..73aad2eb6 100644
--- a/compiler/luci/service/src/Nodes/CircleTransposeConv.cpp
+++ b/compiler/luci/service/src/Nodes/CircleTransposeConv.cpp
@@ -30,6 +30,7 @@ luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleTransposeConv
cloned->padding(node->padding());
cloned->stride()->h(node->stride()->h());
cloned->stride()->w(node->stride()->w());
+ cloned->fusedActivationFunction(node->fusedActivationFunction());
}
return cloned;
}
diff --git a/compiler/luci/service/src/Nodes/CircleTransposeConv.test.cpp b/compiler/luci/service/src/Nodes/CircleTransposeConv.test.cpp
index 29a656c03..e9ac6e6ff 100644
--- a/compiler/luci/service/src/Nodes/CircleTransposeConv.test.cpp
+++ b/compiler/luci/service/src/Nodes/CircleTransposeConv.test.cpp
@@ -32,6 +32,7 @@ TEST(CloneNodeTest, clone_TransposeConv)
auto cloned_trconv = dynamic_cast<luci::CircleTransposeConv *>(cloned);
ASSERT_NE(nullptr, cloned_trconv);
ASSERT_EQ(node_trconv->padding(), cloned_trconv->padding());
+ ASSERT_EQ(node_trconv->fusedActivationFunction(), cloned_trconv->fusedActivationFunction());
}
TEST(CloneNodeTest, clone_TransposeConv_padding_NEG)
@@ -44,3 +45,14 @@ TEST(CloneNodeTest, clone_TransposeConv_padding_NEG)
auto cloned = luci::clone_node(node_trconv, gc.get());
ASSERT_EQ(nullptr, cloned);
}
+
+TEST(CloneNodeTest, clone_TransposeConv_fAF_NEG)
+{
+ auto g = loco::make_graph();
+ auto node_trconv = g->nodes()->create<luci::CircleTransposeConv>();
+ node_trconv->fusedActivationFunction(luci::FusedActFunc::UNDEFINED);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_trconv, gc.get());
+ ASSERT_EQ(nullptr, cloned);
+}
diff --git a/compiler/luci/service/src/ShapeInfer_StridedSlice.cpp b/compiler/luci/service/src/ShapeInfer_StridedSlice.cpp
index 77135cca0..bdd27739a 100644
--- a/compiler/luci/service/src/ShapeInfer_StridedSlice.cpp
+++ b/compiler/luci/service/src/ShapeInfer_StridedSlice.cpp
@@ -43,29 +43,33 @@ const int kMaxDim = 5;
const loco::DataType S32 = loco::DataType::S32;
-using int8 = int8_t;
-using int16 = int16_t;
-
struct StridedSliceParams
{
- int8 start_indices_count = 0;
- int16 start_indices[kMaxDim];
- int8 stop_indices_count = 0;
- int16 stop_indices[kMaxDim];
- int8 strides_count = 0;
- int16 strides[kMaxDim];
-
- int16 begin_mask = 0;
- int16 ellipsis_mask = 0;
- int16 end_mask = 0;
- int16 new_axis_mask = 0;
- int16 shrink_axis_mask = 0;
+ int8_t start_indices_count = 0;
+ int32_t start_indices[kMaxDim];
+ int8_t stop_indices_count = 0;
+ int32_t stop_indices[kMaxDim];
+ int8_t strides_count = 0;
+ int32_t strides[kMaxDim];
+
+ int16_t begin_mask = 0;
+ int16_t ellipsis_mask = 0;
+ int16_t end_mask = 0;
+ int16_t new_axis_mask = 0;
+ int16_t shrink_axis_mask = 0;
};
struct StridedSliceContext
{
StridedSliceContext(const luci::CircleStridedSlice *node)
{
+ // check overflow issues
+ assert(static_cast<int16_t>(node->begin_mask()) == node->begin_mask());
+ assert(static_cast<int16_t>(node->ellipsis_mask()) == node->ellipsis_mask());
+ assert(static_cast<int16_t>(node->end_mask()) == node->end_mask());
+ assert(static_cast<int16_t>(node->new_axis_mask()) == node->new_axis_mask());
+ assert(static_cast<int16_t>(node->shrink_axis_mask()) == node->shrink_axis_mask());
+
params.begin_mask = node->begin_mask();
params.ellipsis_mask = node->ellipsis_mask();
params.end_mask = node->end_mask();
@@ -88,7 +92,7 @@ struct StridedSliceContext
// Equivalent input shape after adding axis according to new_axis_mask.
loco::TensorShape effective_input_shape;
- uint32_t input_dims = 0;
+ int64_t input_dims = 0;
};
// Use until std::clamp() is available from C++17.
@@ -105,19 +109,19 @@ inline int Clamp(const int32_t v, const int32_t lo, const int32_t hi)
// Return the index for the first element along that axis. This index will be a
// positive integer between [0, axis_size - 1] that can be used to index
// directly into the data.
-inline int32_t StartForAxis(const StridedSliceParams &params, const loco::TensorShape &input_shape,
- uint32_t axis)
+inline int64_t StartForAxis(const StridedSliceParams &params, const loco::TensorShape &input_shape,
+ int64_t axis)
{
const auto begin_mask = params.begin_mask;
const auto *start_indices = params.start_indices;
const auto *strides = params.strides;
- const int32_t axis_size = static_cast<int>(input_shape.dim(axis).value());
+ const int64_t axis_size = static_cast<int64_t>(input_shape.dim(axis).value());
if (axis_size == 0)
{
return 0;
}
// Begin with the specified index.
- int32_t start = start_indices[axis];
+ int64_t start = start_indices[axis];
// begin_mask override
if (begin_mask & (1 << axis))
@@ -162,14 +166,14 @@ inline int32_t StartForAxis(const StridedSliceParams &params, const loco::Tensor
// element. ie. So if you were iterating through all elements of a 1D array of
// size 4, this function would return 4 as the stop, because it is one past the
// "real" indices of 0, 1, 2 & 3.
-inline int32_t StopForAxis(const StridedSliceParams &params, const loco::TensorShape &input_shape,
- int32_t axis, int32_t start_for_axis)
+inline int64_t StopForAxis(const StridedSliceParams &params, const loco::TensorShape &input_shape,
+ int64_t axis, int64_t start_for_axis)
{
const auto end_mask = params.end_mask;
const auto shrink_axis_mask = params.shrink_axis_mask;
const auto *stop_indices = params.stop_indices;
const auto *strides = params.strides;
- const int32_t axis_size = static_cast<int32_t>(input_shape.dim(axis).value());
+ const int64_t axis_size = static_cast<int64_t>(input_shape.dim(axis).value());
if (axis_size == 0)
{
return 0;
@@ -177,7 +181,7 @@ inline int32_t StopForAxis(const StridedSliceParams &params, const loco::TensorS
// Begin with the specified index
const bool shrink_axis = shrink_axis_mask & (1 << axis);
- int32_t stop = stop_indices[axis];
+ int64_t stop = stop_indices[axis];
// When shrinking an axis, the end position does not matter (and can be
// incorrect when negative indexing is used, see Issue #19260). Always use
@@ -241,9 +245,9 @@ StridedSliceParams BuildStridedSliceParams(StridedSliceContext *op_context)
// Count indexes where the new_axis_mask is set but the ellipsis_mask is not.
loco::TensorShape begin_shape = luci::shape_get(op_context->begin).as<loco::TensorShape>();
- const uint32_t begin_count = begin_shape.dim(0).value();
- uint32_t num_add_axis = 0;
- for (uint32_t i = 0; i < begin_count; ++i)
+ const int64_t begin_count = static_cast<int64_t>(begin_shape.dim(0).value());
+ int64_t num_add_axis = 0;
+ for (int64_t i = 0; i < begin_count; ++i)
{
if (!((1 << i) & op_context->params.ellipsis_mask) &&
((1 << i) & op_context->params.new_axis_mask))
@@ -253,21 +257,21 @@ StridedSliceParams BuildStridedSliceParams(StridedSliceContext *op_context)
}
// Calculate the dims of input after adding new axises.
- const uint32_t effective_dims = op_context->input_dims + num_add_axis;
+ const int64_t effective_dims = op_context->input_dims + num_add_axis;
// If begin, end and strides are not fully provided, it means Ellipsis should
// be expanded to multiple dimensions (Ex: for spec [Ellipsis, 2] on a 3D
// input, the Ellipsis should be applied for the first 2 dimensions). Besides,
// If the new_axis_mask and the ellipsis_mask are set at the same index, the
// new_axis_mask will have no effect.
- int32_t effective_ellipsis_mask = 0, effective_new_axis_mask = 0;
- uint32_t ellipsis_start_idx = effective_dims, expanded_ellipsis = 0;
- for (uint32_t i = 0; i < effective_dims;)
+ int64_t effective_ellipsis_mask = 0, effective_new_axis_mask = 0;
+ int64_t ellipsis_start_idx = effective_dims, expanded_ellipsis = 0;
+ for (int64_t i = 0; i < effective_dims;)
{
if ((1 << i) & op_context->params.ellipsis_mask)
{
ellipsis_start_idx = i;
- uint32_t ellipsis_end_idx =
+ int64_t ellipsis_end_idx =
std::max(i + 1, std::min(i + 1 + num_add_axis + op_context->input_dims - begin_count,
effective_dims));
expanded_ellipsis = ellipsis_end_idx - ellipsis_start_idx - 1;
@@ -289,15 +293,16 @@ StridedSliceParams BuildStridedSliceParams(StridedSliceContext *op_context)
// Calculate effective_input_shape and its corresponding begin, end, strides.
loco::TensorShape input_shape = luci::shape_get(op_context->input).as<loco::TensorShape>();
- uint32_t added_ellipsis = 0, added_axises = 0;
+ int64_t added_ellipsis = 0, added_axises = 0;
op_context->effective_input_shape.rank(effective_dims);
- for (uint32_t i = 0; i < effective_dims; ++i)
+ for (int64_t i = 0; i < effective_dims; ++i)
{
if ((1 << i) & effective_ellipsis_mask)
{
// If ellipsis_mask, set the begin_mask and end_mask at that index.
- added_ellipsis = std::max(0u, i - ellipsis_start_idx);
+ added_ellipsis = std::max(int64_t(0), i - ellipsis_start_idx);
+ assert(i < 16);
op_params.begin_mask |= (1 << i);
op_params.end_mask |= (1 << i);
op_params.strides[i] = 1;
@@ -318,31 +323,39 @@ StridedSliceParams BuildStridedSliceParams(StridedSliceContext *op_context)
op_params.start_indices[i] = 0;
op_params.stop_indices[i] = 0;
op_params.strides[i] = 1;
+ assert(i < 16);
op_params.begin_mask |= (1 << i);
op_params.end_mask |= (1 << i);
op_context->effective_input_shape.dim(i) = input_shape.dim(i - added_axises);
}
else
{
- const uint32_t orig_idx = i - added_ellipsis;
+ const int64_t orig_idx = i - added_ellipsis;
op_params.start_indices[i] = op_context->begin->at<S32>(orig_idx);
op_params.stop_indices[i] = op_context->end->at<S32>(orig_idx);
op_params.strides[i] = op_context->strides->at<S32>(orig_idx);
if (op_context->params.begin_mask & (1 << orig_idx))
{
+ assert(i < 16);
op_params.begin_mask |= (1 << i);
}
if (op_context->params.end_mask & (1 << orig_idx))
{
+ assert(i < 16);
op_params.end_mask |= (1 << i);
}
if (op_context->params.shrink_axis_mask & (1 << orig_idx))
{
+ assert(i < 16);
op_params.shrink_axis_mask |= (1 << i);
}
op_context->effective_input_shape.dim(i) = input_shape.dim(i - added_axises);
}
}
+
+ // make sure no overflow
+ assert(static_cast<int8_t>(effective_dims) == static_cast<int32_t>(effective_dims));
+
op_params.start_indices_count = effective_dims;
op_params.stop_indices_count = effective_dims;
op_params.strides_count = effective_dims;
@@ -386,15 +399,15 @@ loco::TensorShape infer_output_shape(const CircleStridedSlice *node)
StridedSliceContext op_context(node);
auto op_params = BuildStridedSliceParams(&op_context);
auto effective_input_shape = op_context.effective_input_shape;
- std::vector<int32_t> output_shape_vector;
+ std::vector<int64_t> output_shape_vector;
for (int32_t idx = effective_input_shape.rank() - 1; idx >= 0; --idx)
{
int32_t stride = op_params.strides[idx];
LUCI_ASSERT(stride != 0, "stride value has to be non-zero");
- int32_t begin = StartForAxis(op_params, effective_input_shape, idx);
- int32_t end = StopForAxis(op_params, effective_input_shape, idx, begin);
+ int64_t begin = StartForAxis(op_params, effective_input_shape, idx);
+ int64_t end = StopForAxis(op_params, effective_input_shape, idx, begin);
// When shrinking an axis, the end position does not matter (and can be
// incorrect when negative indexing is used, see Issue #19260). Always use
@@ -407,7 +420,7 @@ loco::TensorShape infer_output_shape(const CircleStridedSlice *node)
}
// This is valid for both positive and negative strides
- int32_t dim_shape = std::ceil((end - begin) / static_cast<float>(stride));
+ int64_t dim_shape = std::ceil((end - begin) / static_cast<float>(stride));
dim_shape = dim_shape < 0 ? 0 : dim_shape;
if (!shrink_axis)
{
@@ -419,8 +432,10 @@ loco::TensorShape infer_output_shape(const CircleStridedSlice *node)
output_shape.rank(shape_size);
for (uint32_t idx = 0; idx < shape_size; ++idx)
{
+ int64_t dim = output_shape_vector.at(shape_size - 1u - idx);
+ LUCI_ASSERT(0 <= dim && dim < 0xfffffffL, "Dimension size exceeds limit");
// reverse copy
- output_shape.dim(idx) = output_shape_vector.at(shape_size - 1u - idx);
+ output_shape.dim(idx) = static_cast<uint32_t>(dim);
}
return output_shape;
diff --git a/compiler/luci/service/src/Validate.cpp b/compiler/luci/service/src/Validate.cpp
index 2f78e059e..3f6f9c01e 100644
--- a/compiler/luci/service/src/Validate.cpp
+++ b/compiler/luci/service/src/Validate.cpp
@@ -82,6 +82,65 @@ luci::CircleOutput *find_node(std::vector<loco::Node *> nodes, loco::GraphOutput
return nullptr;
}
+// TODO Reduce duplicate with validate_shape_dtype
+bool validate_shape(loco::Graph *g)
+{
+ LOGGER(l);
+
+ auto output_nodes = loco::output_nodes(g);
+
+ auto count = g->outputs()->size();
+ for (uint32_t out = 0; out < count; ++out)
+ {
+ auto graph_out = g->outputs()->at(out);
+ auto out_index = graph_out->index();
+
+ auto circle_output = find_node(output_nodes, out_index);
+ assert(circle_output != nullptr);
+ assert(circle_output->from() != nullptr);
+ auto circle_node = loco::must_cast<luci::CircleNode *>(circle_output->from());
+
+ // Shape validation for CircleOutputExclude is not needed
+ if (dynamic_cast<luci::CircleOutputExclude *>(circle_node))
+ continue;
+
+ assert(circle_node->shape_status() != luci::ShapeStatus::UNDEFINED);
+
+ // check if output node shape is same as graph output shape
+ auto go_tensor_shape = graph_out->shape();
+ assert(go_tensor_shape);
+
+ // NOTE Even if shape of graph output is [] (which means "shape inference was impossible")
+ // but shape of CircleNode is not, it can be valid case because shape inference
+ // algorithm of CircleNode may be upgraded than before. The opposite is possible either.
+ // If such cases are appeared, following validation code should be fixed.
+ bool is_shape_valid = (circle_node->rank() == go_tensor_shape->rank());
+ for (uint32_t i = 0; is_shape_valid && i < circle_node->rank(); ++i)
+ {
+ if (!circle_node->dim(i).known() || !go_tensor_shape->dim(i).known())
+ {
+ // If at least one of two dimensions is unknown,
+ // the unknown dimension can accept any value.
+ INFO(l) << "Unknown dimension is matched with known dimension" << std::endl;
+ }
+ else if (circle_node->dim(i).value() != go_tensor_shape->dim(i).value())
+ {
+ is_shape_valid = false;
+ }
+ }
+
+ if (is_shape_valid == false)
+ {
+ INFO(l) << "[luci] Shape for output #" << out_index << " not same " << std::endl;
+ INFO(l) << "[luci] " << circle_node->name() << " " << circle_node << " vs "
+ << *go_tensor_shape << std::endl;
+ return false;
+ }
+ }
+
+ return true;
+}
+
bool validate_shape_dtype(loco::Graph *g)
{
LOGGER(l);
@@ -249,6 +308,17 @@ public:
namespace luci
{
+bool validate_shape(loco::Graph *g)
+{
+ if (!loco::valid(g))
+ return false;
+
+ if (!::validate_shape(g))
+ return false;
+
+ return true;
+}
+
bool validate(loco::Graph *g)
{
if (!loco::valid(g))
@@ -358,4 +428,26 @@ bool validate(luci::Module *module)
return true;
}
+bool validate_shape(luci::Module *module)
+{
+ LOGGER(l);
+
+ INFO(l) << "--- validate shape of Module -----------------------------------";
+
+ for (size_t g = 0; g < module->size(); ++g)
+ {
+ auto graph = module->graph(g);
+
+ INFO(l) << luci::fmt(graph) << std::endl;
+
+ if (!validate_shape(graph))
+ {
+ std::cerr << "ERROR: Invalid circle model" << std::endl;
+ return false;
+ }
+ }
+
+ return true;
+}
+
} // namespace luci
diff --git a/compiler/luci/tests/test.lst b/compiler/luci/tests/test.lst
index 8291f20e3..a88661db3 100644
--- a/compiler/luci/tests/test.lst
+++ b/compiler/luci/tests/test.lst
@@ -69,8 +69,10 @@ addread(FullyConnected_002)
addread(FullyConnected_U8_000)
addread(Gather_000)
addread(GatherNd_000)
+addread(Gelu_000)
addread(Greater_000)
addread(GreaterEqual_000)
+addread(HardSwish_000)
addread(If_000)
addread(If_001)
addread(L2Normalize_000)
@@ -297,8 +299,10 @@ addwrite(FullyConnected_002)
addwrite(FullyConnected_U8_000)
addwrite(Gather_000)
addwrite(GatherNd_000)
+addwrite(Gelu_000)
addwrite(Greater_000)
addwrite(GreaterEqual_000)
+addwrite(HardSwish_000)
addwrite(If_000)
addwrite(If_001)
addwrite(L2Normalize_000)
diff --git a/compiler/mio-circle05/CMakeLists.txt b/compiler/mio-circle05/CMakeLists.txt
new file mode 100644
index 000000000..dfd359eaa
--- /dev/null
+++ b/compiler/mio-circle05/CMakeLists.txt
@@ -0,0 +1,52 @@
+nnas_find_package(FlatBuffers EXACT 2.0 QUIET)
+
+if(NOT FlatBuffers_FOUND)
+ message(STATUS "mio-circle05 skip: FlatBuffers 2.0 NOT FOUND")
+ return()
+endif(NOT FlatBuffers_FOUND)
+
+message(STATUS "Build mio-circle05: TRUE")
+
+# TODO Find a better way
+# TODO use nnpackage
+# set(SCHEMA_FILE "${NNAS_PROJECT_SOURCE_DIR}/nnpackage/schema/circle_schema.fbs")
+set(SCHEMA_FILE "${NNAS_PROJECT_SOURCE_DIR}/res/CircleSchema/0.5/circle_schema.fbs")
+
+# NOTE Copy circle_schema.fbs as schema.fbs to generate "schema_generated.fbs" instead of "circle_schema_generated.fbs"
+add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/schema.fbs"
+ COMMAND ${CMAKE_COMMAND} -E copy "${SCHEMA_FILE}" schema.fbs
+ WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
+ DEPENDS "${SCHEMA_FILE}"
+)
+
+FlatBuffers_Target(mio_circle05
+ OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/gen/mio/circle"
+ INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/gen"
+ SCHEMA_DIR "${CMAKE_CURRENT_BINARY_DIR}"
+ SCHEMA_FILES "schema.fbs"
+)
+
+# This example shows how to use "mio-circle05" library
+add_executable(mio_circle05_example example.cpp)
+target_link_libraries(mio_circle05_example mio_circle05)
+
+file(GLOB_RECURSE SOURCES "src/*.cpp")
+file(GLOB_RECURSE TESTS "src/*.test.cpp")
+list(REMOVE_ITEM SOURCES ${TESTS})
+
+add_library(mio_circle05_helper STATIC ${SOURCES})
+set_target_properties(mio_circle05_helper PROPERTIES POSITION_INDEPENDENT_CODE ON)
+target_include_directories(mio_circle05_helper PRIVATE src)
+target_include_directories(mio_circle05_helper PUBLIC include)
+target_link_libraries(mio_circle05_helper mio_circle05)
+
+if(NOT ENABLE_TEST)
+ return()
+endif(NOT ENABLE_TEST)
+
+nnas_find_package(GTest REQUIRED)
+
+GTest_AddTest(mio_circle05_helper_test ${TESTS})
+target_include_directories(mio_circle05_helper_test PRIVATE src)
+target_link_libraries(mio_circle05_helper_test mio_circle05)
+target_link_libraries(mio_circle05_helper_test mio_circle05_helper)
diff --git a/compiler/mio-circle05/README.md b/compiler/mio-circle05/README.md
new file mode 100644
index 000000000..929643658
--- /dev/null
+++ b/compiler/mio-circle05/README.md
@@ -0,0 +1,3 @@
+# mio-circle05
+
+Let's make it easy to read and write Circle models.
diff --git a/compiler/mio-circle05/example.cpp b/compiler/mio-circle05/example.cpp
new file mode 100644
index 000000000..31cd3fbe5
--- /dev/null
+++ b/compiler/mio-circle05/example.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//
+// This example shows how to include and use "mio-circle05"
+//
+#include <mio/circle/schema_generated.h>
+
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+int main(int argc, char **argv)
+{
+ std::ifstream ifs(argv[1], std::ios_base::binary);
+ std::vector<char> buf(std::istreambuf_iterator<char>{ifs}, std::istreambuf_iterator<char>{});
+
+ flatbuffers::Verifier verifier{reinterpret_cast<uint8_t *>(buf.data()), buf.size()};
+
+ if (!circle::VerifyModelBuffer(verifier))
+ {
+ std::cout << "Fail" << std::endl;
+ return 255;
+ }
+
+ std::cout << "Pass" << std::endl;
+ return 0;
+}
diff --git a/compiler/mio-circle05/include/mio_circle/Helper.h b/compiler/mio-circle05/include/mio_circle/Helper.h
new file mode 100644
index 000000000..933f38587
--- /dev/null
+++ b/compiler/mio-circle05/include/mio_circle/Helper.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MIO_CIRCLE05_HELPER_H__
+#define __MIO_CIRCLE05_HELPER_H__
+
+#include <mio/circle/schema_generated.h>
+
+#include <vector>
+
+namespace mio
+{
+namespace circle
+{
+
+::circle::BuiltinOperator builtin_code_neutral(const ::circle::OperatorCode *opcode);
+bool is_valid(const ::circle::OperatorCode *opcode);
+bool is_custom(const ::circle::OperatorCode *opcode);
+std::string opcode_name(const ::circle::OperatorCode *opcode);
+const char *tensor_type(const ::circle::Tensor *tensor);
+const char *tensor_name(const ::circle::Tensor *tensor);
+
+template <typename T> std::vector<T> as_index_vector(const flatbuffers::Vector<T> *flat_array)
+{
+ if (flat_array == nullptr)
+ {
+ throw std::runtime_error("flat array is nullptr");
+ }
+
+ std::vector<T> ret(flat_array->Length());
+ for (uint32_t i = 0; i < flat_array->Length(); i++)
+ {
+ ret[i] = flat_array->Get(i);
+ }
+ return ret;
+}
+
+} // namespace circle
+} // namespace mio
+
+#endif // __MIO_CIRCLE05_HELPER_H__
diff --git a/compiler/mio-circle05/include/mio_circle/Reader.h b/compiler/mio-circle05/include/mio_circle/Reader.h
new file mode 100644
index 000000000..d751a30c6
--- /dev/null
+++ b/compiler/mio-circle05/include/mio_circle/Reader.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MIO_CIRCLE05_READER_H__
+#define __MIO_CIRCLE05_READER_H__
+
+#include <mio/circle/schema_generated.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+// NOTE Reader class originated from circledump and for circle-tensordump
+// where this class has more work to be done for stability
+// as the tools are for developers not customores.
+
+namespace mio
+{
+namespace circle
+{
+
+/**
+ * @brief Loads Circle file and provides helpers to access attributes
+ */
+class Reader
+{
+private:
+ using CircleSubGraphs_t = flatbuffers::Vector<flatbuffers::Offset<::circle::SubGraph>>;
+ using CircleBuffers_t = flatbuffers::Vector<flatbuffers::Offset<::circle::Buffer>>;
+ using CircleTensors_t = flatbuffers::Vector<flatbuffers::Offset<::circle::Tensor>>;
+ using CircleOperators_t = flatbuffers::Vector<flatbuffers::Offset<::circle::Operator>>;
+ using CircleMetadata_t = flatbuffers::Vector<flatbuffers::Offset<::circle::Metadata>>;
+ using CircleSignatureDef_t = flatbuffers::Vector<flatbuffers::Offset<::circle::SignatureDef>>;
+
+public:
+ Reader(const ::circle::Model *model);
+
+ Reader() = delete;
+
+public:
+ uint32_t version() const { return _version; }
+
+ const std::vector<const ::circle::OperatorCode *> &opcodes() { return _op_codes; }
+ const CircleBuffers_t *buffers() { return _buffers; }
+ const CircleTensors_t *tensors() { return _tensors; }
+ const CircleOperators_t *operators() { return _operators; }
+ const std::vector<int32_t> &inputs() const { return _inputs; }
+ const std::vector<int32_t> &outputs() const { return _outputs; }
+ const ::circle::DataFormat &data_format() const { return _data_format; }
+ const CircleMetadata_t *metadata() const { return _metadata; }
+ const CircleSignatureDef_t *signature_defs() const { return _signature_defs; }
+
+ uint32_t num_subgraph() const { return _subgraphs->Length(); }
+
+ size_t buffer_info(uint32_t buf_idx, const uint8_t **buff_data);
+ ::circle::BuiltinOperator builtin_code(const ::circle::Operator *op) const;
+ std::string opcode_name(const ::circle::Operator *op) const;
+ std::vector<int32_t> outputs(const ::circle::Operator *op) const;
+ std::string tensor_name(const ::circle::Tensor *tensor) const;
+ std::string tensor_dtype(const ::circle::Tensor *tensor) const;
+
+public:
+ bool select_subgraph(uint32_t subgraph);
+ const std::string &subgraph_name(void) const { return _subgraph_name; }
+ uint32_t subgraph_index(void) const { return _subgraph_index; }
+
+private:
+ uint32_t _version;
+
+ const CircleSubGraphs_t *_subgraphs{nullptr};
+ const CircleBuffers_t *_buffers{nullptr};
+ const CircleTensors_t *_tensors{nullptr};
+ const CircleOperators_t *_operators{nullptr};
+ const CircleMetadata_t *_metadata{nullptr};
+ const CircleSignatureDef_t *_signature_defs{nullptr};
+
+ uint32_t _subgraph_index = 0;
+ std::string _subgraph_name;
+ std::vector<const ::circle::OperatorCode *> _op_codes;
+ std::vector<int32_t> _inputs;
+ std::vector<int32_t> _outputs;
+ ::circle::DataFormat _data_format = ::circle::DataFormat::DataFormat_CHANNELS_FIRST;
+};
+
+} // namespace circle
+} // namespace mio
+
+#endif // __MIO_CIRCLE05_READER_H__
diff --git a/compiler/mio-circle05/src/Helper.cpp b/compiler/mio-circle05/src/Helper.cpp
new file mode 100644
index 000000000..bbfa2041a
--- /dev/null
+++ b/compiler/mio-circle05/src/Helper.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mio_circle/Helper.h"
+
+#include <algorithm>
+#include <sstream>
+
+namespace mio
+{
+namespace circle
+{
+
+/**
+ * This will provide v3/v3a/v3b format neutral BuiltinOperator
+ * NOTE circle has minus value opcode (252~254 as uint8_t)
+ * we cannot use std::max() like tflite as deprecated_builtin_code can be
+ * minus and builtin_code being 0 for v0.3 files.
+ */
+::circle::BuiltinOperator builtin_code_neutral(const ::circle::OperatorCode *opcode)
+{
+ assert(opcode != nullptr);
+ if (opcode->deprecated_builtin_code() == 127)
+ {
+ assert(opcode->builtin_code() >= 127);
+ return opcode->builtin_code();
+ }
+ // There was no 255(-1) value in v0.3
+ assert(opcode->deprecated_builtin_code() != -1);
+ return static_cast<::circle::BuiltinOperator>(opcode->deprecated_builtin_code());
+}
+
+bool is_valid(const ::circle::OperatorCode *opcode)
+{
+ // Valid Range : BuiltinOperator_MIN <= deprecated_builtin_code <= 127
+ const int8_t deprecated_builtin_code = opcode->deprecated_builtin_code();
+ if (deprecated_builtin_code < ::circle::BuiltinOperator_MIN)
+ return false;
+ // There was no 255(-1) value in v0.3
+ if (deprecated_builtin_code == -1)
+ return false;
+
+ const ::circle::BuiltinOperator builtin_code = opcode->builtin_code();
+ if (!(::circle::BuiltinOperator_MIN <= builtin_code &&
+ builtin_code <= ::circle::BuiltinOperator_MAX))
+ return false;
+
+ return true;
+}
+
+bool is_custom(const ::circle::OperatorCode *opcode)
+{
+ ::circle::BuiltinOperator code = builtin_code_neutral(opcode);
+ return (code == ::circle::BuiltinOperator_CUSTOM);
+}
+
+std::string opcode_name(const ::circle::OperatorCode *opcode)
+{
+ assert(opcode);
+
+ if (!is_valid(opcode))
+ {
+ std::ostringstream oss;
+ oss << "(invalid)";
+ return oss.str();
+ }
+
+ if (is_custom(opcode))
+ {
+ if (!opcode->custom_code())
+ return "(invalid custom)";
+
+ std::string custom_op = "CUSTOM(";
+ custom_op += opcode->custom_code()->c_str();
+ custom_op += ")";
+ return custom_op;
+ }
+
+ ::circle::BuiltinOperator code = builtin_code_neutral(opcode);
+ return ::circle::EnumNameBuiltinOperator(code);
+}
+
+const char *tensor_type(const ::circle::Tensor *tensor)
+{
+ return ::circle::EnumNameTensorType(tensor->type());
+}
+
+const char *tensor_name(const ::circle::Tensor *tensor)
+{
+ if (tensor->name() == nullptr || std::string(tensor->name()->c_str()).empty())
+ return "(noname)";
+
+ return tensor->name()->c_str();
+}
+
+} // namespace circle
+} // namespace mio
diff --git a/compiler/mio-circle05/src/Helper.test.cpp b/compiler/mio-circle05/src/Helper.test.cpp
new file mode 100644
index 000000000..be63688df
--- /dev/null
+++ b/compiler/mio-circle05/src/Helper.test.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mio_circle/Helper.h"
+
+#include <flatbuffers/flatbuffers.h>
+#include <gtest/gtest.h>
+
+#include <vector>
+
+class mio_circle05_helper_test : public ::testing::Test
+{
+protected:
+ void initialization_finish(void)
+ {
+ _fbb.Finish(circle::CreateModelDirect(_fbb, 0, &_opcodes_vec));
+ }
+
+protected:
+ void add_operator_code(int8_t deprecated_builtin_code, const char *custom_code,
+ circle::BuiltinOperator builtin_code)
+ {
+ _opcodes_vec.push_back(circle::CreateOperatorCodeDirect(
+ _fbb, deprecated_builtin_code, custom_code, 1 /* version */, builtin_code));
+ }
+
+ const circle::OperatorCode *get_operator_code(uint8_t idx)
+ {
+ return circle::GetModel(_fbb.GetBufferPointer())->operator_codes()->Get(idx);
+ }
+
+private:
+ flatbuffers::FlatBufferBuilder _fbb;
+ std::vector<flatbuffers::Offset<circle::OperatorCode>> _opcodes_vec;
+};
+
+TEST_F(mio_circle05_helper_test, v05)
+{
+ // BuiltinOperator_ADD = 0
+ // BuiltinOperator_CONV_2D = 3
+ add_operator_code(3, "", circle::BuiltinOperator_ADD);
+ initialization_finish();
+
+ ASSERT_TRUE(mio::circle::is_valid(get_operator_code(0)));
+ ASSERT_EQ(mio::circle::builtin_code_neutral(get_operator_code(0)),
+ circle::BuiltinOperator_CONV_2D);
+ ASSERT_FALSE(mio::circle::is_custom(get_operator_code(0)));
+}
+
+TEST_F(mio_circle05_helper_test, v05_custom_old)
+{
+ // BuiltinOperator_ADD = 0
+ // BuiltinOperator_CUSTOM = 32
+ add_operator_code(32, "custom", circle::BuiltinOperator_ADD);
+ initialization_finish();
+
+ ASSERT_TRUE(mio::circle::is_valid(get_operator_code(0)));
+ ASSERT_EQ(mio::circle::builtin_code_neutral(get_operator_code(0)),
+ circle::BuiltinOperator_CUSTOM);
+ ASSERT_TRUE(mio::circle::is_custom(get_operator_code(0)));
+}
+
+TEST_F(mio_circle05_helper_test, v05_NEG)
+{
+ // BuiltinOperator_ADD = 0
+ // BuiltinOperator_CUMSUM = 128
+ // deprecated_builtin_code cannot be negative value
+ add_operator_code(128, "", circle::BuiltinOperator_ADD);
+ initialization_finish();
+
+ ASSERT_FALSE(mio::circle::is_valid(get_operator_code(0)));
+}
+
+TEST_F(mio_circle05_helper_test, v05_under127)
+{
+ // BuiltinOperator_CONV_2D = 3
+ add_operator_code(3, "", circle::BuiltinOperator_CONV_2D);
+ initialization_finish();
+
+ ASSERT_TRUE(mio::circle::is_valid(get_operator_code(0)));
+ ASSERT_EQ(mio::circle::builtin_code_neutral(get_operator_code(0)),
+ circle::BuiltinOperator_CONV_2D);
+ ASSERT_FALSE(mio::circle::is_custom(get_operator_code(0)));
+}
+
+TEST_F(mio_circle05_helper_test, v05_under127_NEG)
+{
+ // BuiltinOperator_CONV_2D = 3
+ // BuiltinOperator_CUMSUM = 128
+ // deprecated_builtin_code cannot be negative value
+ add_operator_code(128, "", circle::BuiltinOperator_CONV_2D);
+ initialization_finish();
+
+ ASSERT_FALSE(mio::circle::is_valid(get_operator_code(0)));
+}
+
+TEST_F(mio_circle05_helper_test, v05_custom)
+{
+ // BuiltinOperator_CUSTOM = 32
+ add_operator_code(32, "custom", circle::BuiltinOperator_CUSTOM);
+ initialization_finish();
+
+ ASSERT_TRUE(mio::circle::is_valid(get_operator_code(0)));
+ ASSERT_EQ(mio::circle::builtin_code_neutral(get_operator_code(0)),
+ circle::BuiltinOperator_CUSTOM);
+ ASSERT_TRUE(mio::circle::is_custom(get_operator_code(0)));
+}
+
+TEST_F(mio_circle05_helper_test, v05_custom_NEG)
+{
+ // BuiltinOperator_CUMSUM = 128
+ // deprecated_builtin_code cannot be negative value
+ add_operator_code(128, "custom", circle::BuiltinOperator_CUSTOM);
+ initialization_finish();
+
+ ASSERT_FALSE(mio::circle::is_valid(get_operator_code(0)));
+}
+
+TEST_F(mio_circle05_helper_test, v05_over127)
+{
+ // BuiltinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES = 127
+ // BuiltinOperator_CUMSUM = 128
+ add_operator_code(127, "", circle::BuiltinOperator_CUMSUM);
+ initialization_finish();
+
+ ASSERT_TRUE(mio::circle::is_valid(get_operator_code(0)));
+ ASSERT_EQ(mio::circle::builtin_code_neutral(get_operator_code(0)),
+ circle::BuiltinOperator_CUMSUM);
+ ASSERT_FALSE(mio::circle::is_custom(get_operator_code(0)));
+}
+
+TEST_F(mio_circle05_helper_test, v05_over127_NEG)
+{
+ // BuiltinOperator_CUMSUM = 128
+ // deprecated_builtin_code cannot be negative value
+ add_operator_code(128, "", circle::BuiltinOperator_CUMSUM);
+ initialization_finish();
+
+ ASSERT_FALSE(mio::circle::is_valid(get_operator_code(0)));
+}
diff --git a/compiler/mio-circle05/src/Reader.cpp b/compiler/mio-circle05/src/Reader.cpp
new file mode 100644
index 000000000..0ee22db14
--- /dev/null
+++ b/compiler/mio-circle05/src/Reader.cpp
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mio_circle/Reader.h"
+#include "mio_circle/Helper.h"
+
+#include <sstream>
+#include <string>
+
+namespace mio
+{
+namespace circle
+{
+
+Reader::Reader(const ::circle::Model *model)
+{
+ if (model == nullptr)
+ {
+ throw std::runtime_error("Invalid model");
+ }
+
+ _version = model->version();
+ _subgraphs = model->subgraphs();
+ _buffers = model->buffers();
+ _metadata = model->metadata();
+ _signature_defs = model->signature_defs();
+
+ auto opcodes = model->operator_codes();
+ for (const ::circle::OperatorCode *opcode : *opcodes)
+ {
+ _op_codes.push_back(opcode);
+ }
+}
+
+size_t Reader::buffer_info(uint32_t buf_idx, const uint8_t **buff_data)
+{
+ if (buff_data != nullptr)
+ {
+ *buff_data = nullptr;
+ }
+
+ if (buf_idx == 0)
+ return 0;
+
+ if (auto *buffer = (*_buffers)[buf_idx])
+ {
+ if (auto *array = buffer->data())
+ {
+ if (size_t size = array->size())
+ {
+ if (buff_data != nullptr)
+ {
+ *buff_data = reinterpret_cast<const uint8_t *>(array->data());
+ }
+ return size;
+ }
+ }
+ }
+
+ return 0;
+}
+
+::circle::BuiltinOperator Reader::builtin_code(const ::circle::Operator *op) const
+{
+ uint32_t index = op->opcode_index();
+ assert(index < _op_codes.size());
+ const ::circle::OperatorCode *opcode = _op_codes.at(index);
+
+ return mio::circle::builtin_code_neutral(opcode);
+}
+
+std::string Reader::opcode_name(const ::circle::Operator *op) const
+{
+ uint32_t index = op->opcode_index();
+ assert(index < _op_codes.size());
+ const ::circle::OperatorCode *opcode = _op_codes.at(index);
+
+ if (!mio::circle::is_valid(opcode))
+ {
+ std::ostringstream oss;
+ oss << "(invalid: " << index << ")";
+ return oss.str();
+ }
+
+ return mio::circle::opcode_name(opcode);
+}
+
+std::vector<int32_t> Reader::outputs(const ::circle::Operator *op) const
+{
+ return as_index_vector(op->outputs());
+}
+
+std::string Reader::tensor_name(const ::circle::Tensor *tensor) const
+{
+ return mio::circle::tensor_name(tensor);
+}
+
+std::string Reader::tensor_dtype(const ::circle::Tensor *tensor) const
+{
+ return mio::circle::tensor_type(tensor);
+}
+
+bool Reader::select_subgraph(uint32_t sgindex)
+{
+ _subgraph_index = sgindex;
+ _tensors = nullptr;
+ _operators = nullptr;
+
+ _inputs.clear();
+ _outputs.clear();
+
+ if (_subgraphs->Length() <= sgindex)
+ {
+ assert(false);
+ return false;
+ }
+
+ const ::circle::SubGraph *subgraph = (*_subgraphs)[sgindex];
+
+ auto name = subgraph->name();
+ _subgraph_name = name ? name->c_str() : "(noname)";
+
+ _tensors = subgraph->tensors();
+ _operators = subgraph->operators();
+ _data_format = subgraph->data_format();
+
+ _inputs = as_index_vector(subgraph->inputs());
+ _outputs = as_index_vector(subgraph->outputs());
+
+ return true;
+}
+
+} // namespace circle
+} // namespace mio
diff --git a/compiler/mio-circle05/src/Reader.test.cpp b/compiler/mio-circle05/src/Reader.test.cpp
new file mode 100644
index 000000000..0c60999f4
--- /dev/null
+++ b/compiler/mio-circle05/src/Reader.test.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mio_circle/Reader.h"
+
+#include <flatbuffers/flatbuffers.h>
+#include <gtest/gtest.h>
+
+class mio_circle05_reader_test : public ::testing::Test
+{
+protected:
+ void initialization_emty(void)
+ {
+ _model = circle::CreateModelDirect(_fbb, 0, &_opcodes_vec);
+ circle::FinishModelBuffer(_fbb, _model);
+ }
+
+ const circle::Model *circleModel(void)
+ {
+ auto ptr = _fbb.GetBufferPointer();
+ return circle::GetModel(ptr);
+ }
+
+private:
+ flatbuffers::FlatBufferBuilder _fbb;
+ flatbuffers::Offset<circle::Model> _model;
+ std::vector<flatbuffers::Offset<circle::OperatorCode>> _opcodes_vec;
+};
+
+TEST_F(mio_circle05_reader_test, null_Model_NEG)
+{
+ EXPECT_THROW(mio::circle::Reader reader(nullptr), std::runtime_error);
+}
+
+TEST_F(mio_circle05_reader_test, empty_Model)
+{
+ initialization_emty();
+
+ const circle::Model *model = circleModel();
+ EXPECT_NE(nullptr, model);
+
+ mio::circle::Reader reader(model);
+
+ SUCCEED();
+}
+
+// TODO add more tests
diff --git a/compiler/mio-circle06/CMakeLists.txt b/compiler/mio-circle06/CMakeLists.txt
new file mode 100644
index 000000000..2ccd8059c
--- /dev/null
+++ b/compiler/mio-circle06/CMakeLists.txt
@@ -0,0 +1,52 @@
+nnas_find_package(FlatBuffers EXACT 2.0 QUIET)
+
+if(NOT FlatBuffers_FOUND)
+ message(STATUS "mio-circle06 skip: FlatBuffers 2.0 NOT FOUND")
+ return()
+endif(NOT FlatBuffers_FOUND)
+
+message(STATUS "Build mio-circle06: TRUE")
+
+# TODO Find a better way
+# TODO use nnpackage
+# set(SCHEMA_FILE "${NNAS_PROJECT_SOURCE_DIR}/nnpackage/schema/circle_schema.fbs")
+set(SCHEMA_FILE "${NNAS_PROJECT_SOURCE_DIR}/res/CircleSchema/0.6/circle_schema.fbs")
+
+# NOTE Copy circle_schema.fbs as schema.fbs to generate "schema_generated.fbs" instead of "circle_schema_generated.fbs"
+add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/schema.fbs"
+ COMMAND ${CMAKE_COMMAND} -E copy "${SCHEMA_FILE}" schema.fbs
+ WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
+ DEPENDS "${SCHEMA_FILE}"
+)
+
+FlatBuffers_Target(mio_circle06
+ OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/gen/mio/circle"
+ INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/gen"
+ SCHEMA_DIR "${CMAKE_CURRENT_BINARY_DIR}"
+ SCHEMA_FILES "schema.fbs"
+)
+
+# This example shows how to use "mio-circle06" library
+add_executable(mio_circle06_example example.cpp)
+target_link_libraries(mio_circle06_example mio_circle06)
+
+file(GLOB_RECURSE SOURCES "src/*.cpp")
+file(GLOB_RECURSE TESTS "src/*.test.cpp")
+list(REMOVE_ITEM SOURCES ${TESTS})
+
+add_library(mio_circle06_helper STATIC ${SOURCES})
+set_target_properties(mio_circle06_helper PROPERTIES POSITION_INDEPENDENT_CODE ON)
+target_include_directories(mio_circle06_helper PRIVATE src)
+target_include_directories(mio_circle06_helper PUBLIC include)
+target_link_libraries(mio_circle06_helper mio_circle06)
+
+if(NOT ENABLE_TEST)
+ return()
+endif(NOT ENABLE_TEST)
+
+nnas_find_package(GTest REQUIRED)
+
+GTest_AddTest(mio_circle06_helper_test ${TESTS})
+target_include_directories(mio_circle06_helper_test PRIVATE src)
+target_link_libraries(mio_circle06_helper_test mio_circle06)
+target_link_libraries(mio_circle06_helper_test mio_circle06_helper)
diff --git a/compiler/mio-circle06/README.md b/compiler/mio-circle06/README.md
new file mode 100644
index 000000000..c84296416
--- /dev/null
+++ b/compiler/mio-circle06/README.md
@@ -0,0 +1,3 @@
+# mio-circle06
+
+Let's make it easy to read and write Circle models.
diff --git a/compiler/mio-circle06/example.cpp b/compiler/mio-circle06/example.cpp
new file mode 100644
index 000000000..e99e45429
--- /dev/null
+++ b/compiler/mio-circle06/example.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//
+// This example shows how to include and use "mio-circle06"
+//
+#include <mio/circle/schema_generated.h>
+
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+int main(int argc, char **argv)
+{
+ std::ifstream ifs(argv[1], std::ios_base::binary);
+ std::vector<char> buf(std::istreambuf_iterator<char>{ifs}, std::istreambuf_iterator<char>{});
+
+ flatbuffers::Verifier verifier{reinterpret_cast<uint8_t *>(buf.data()), buf.size()};
+
+ if (!circle::VerifyModelBuffer(verifier))
+ {
+ std::cout << "Fail" << std::endl;
+ return 255;
+ }
+
+ std::cout << "Pass" << std::endl;
+ return 0;
+}
diff --git a/compiler/mio-circle06/include/mio_circle/Helper.h b/compiler/mio-circle06/include/mio_circle/Helper.h
new file mode 100644
index 000000000..55cab5872
--- /dev/null
+++ b/compiler/mio-circle06/include/mio_circle/Helper.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MIO_CIRCLE06_HELPER_H__
+#define __MIO_CIRCLE06_HELPER_H__
+
+#include <mio/circle/schema_generated.h>
+
+#include <vector>
+
+namespace mio
+{
+namespace circle
+{
+
+::circle::BuiltinOperator builtin_code_neutral(const ::circle::OperatorCode *opcode);
+bool is_valid(const ::circle::OperatorCode *opcode);
+bool is_custom(const ::circle::OperatorCode *opcode);
+std::string opcode_name(const ::circle::OperatorCode *opcode);
+const char *tensor_type(const ::circle::Tensor *tensor);
+const char *tensor_name(const ::circle::Tensor *tensor);
+
+template <typename T> std::vector<T> as_index_vector(const flatbuffers::Vector<T> *flat_array)
+{
+ if (flat_array == nullptr)
+ {
+ throw std::runtime_error("flat array is nullptr");
+ }
+
+ std::vector<T> ret(flat_array->Length());
+ for (uint32_t i = 0; i < flat_array->Length(); i++)
+ {
+ ret[i] = flat_array->Get(i);
+ }
+ return ret;
+}
+
+} // namespace circle
+} // namespace mio
+
+#endif // __MIO_CIRCLE06_HELPER_H__
diff --git a/compiler/mio-circle06/include/mio_circle/Reader.h b/compiler/mio-circle06/include/mio_circle/Reader.h
new file mode 100644
index 000000000..357061480
--- /dev/null
+++ b/compiler/mio-circle06/include/mio_circle/Reader.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MIO_CIRCLE06_READER_H__
+#define __MIO_CIRCLE06_READER_H__
+
+#include <mio/circle/schema_generated.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+// NOTE Reader class originated from circledump and for circle-tensordump
+// where this class has more work to be done for stability
+// as the tools are for developers not customores.
+
+namespace mio
+{
+namespace circle
+{
+
+/**
+ * @brief Loads Circle file and provides helpers to access attributes
+ */
+class Reader
+{
+private:
+ using CircleSubGraphs_t = flatbuffers::Vector<flatbuffers::Offset<::circle::SubGraph>>;
+ using CircleBuffers_t = flatbuffers::Vector<flatbuffers::Offset<::circle::Buffer>>;
+ using CircleTensors_t = flatbuffers::Vector<flatbuffers::Offset<::circle::Tensor>>;
+ using CircleOperators_t = flatbuffers::Vector<flatbuffers::Offset<::circle::Operator>>;
+ using CircleMetadata_t = flatbuffers::Vector<flatbuffers::Offset<::circle::Metadata>>;
+ using CircleSignatureDef_t = flatbuffers::Vector<flatbuffers::Offset<::circle::SignatureDef>>;
+
+public:
+ Reader(const ::circle::Model *model);
+
+ Reader() = delete;
+
+public:
+ uint32_t version() const { return _version; }
+
+ const std::vector<const ::circle::OperatorCode *> &opcodes() { return _op_codes; }
+ const CircleBuffers_t *buffers() { return _buffers; }
+ const CircleTensors_t *tensors() { return _tensors; }
+ const CircleOperators_t *operators() { return _operators; }
+ const std::vector<int32_t> &inputs() const { return _inputs; }
+ const std::vector<int32_t> &outputs() const { return _outputs; }
+ const ::circle::DataFormat &data_format() const { return _data_format; }
+ const CircleMetadata_t *metadata() const { return _metadata; }
+ const CircleSignatureDef_t *signature_defs() const { return _signature_defs; }
+
+ uint32_t num_subgraph() const { return _subgraphs->Length(); }
+
+ size_t buffer_info(uint32_t buf_idx, const uint8_t **buff_data);
+ ::circle::BuiltinOperator builtin_code(const ::circle::Operator *op) const;
+ std::string opcode_name(const ::circle::Operator *op) const;
+ std::vector<int32_t> outputs(const ::circle::Operator *op) const;
+ std::string tensor_name(const ::circle::Tensor *tensor) const;
+ std::string tensor_dtype(const ::circle::Tensor *tensor) const;
+
+public:
+ bool select_subgraph(uint32_t subgraph);
+ const std::string &subgraph_name(void) const { return _subgraph_name; }
+ uint32_t subgraph_index(void) const { return _subgraph_index; }
+
+private:
+ uint32_t _version;
+
+ const CircleSubGraphs_t *_subgraphs{nullptr};
+ const CircleBuffers_t *_buffers{nullptr};
+ const CircleTensors_t *_tensors{nullptr};
+ const CircleOperators_t *_operators{nullptr};
+ const CircleMetadata_t *_metadata{nullptr};
+ const CircleSignatureDef_t *_signature_defs{nullptr};
+
+ uint32_t _subgraph_index = 0;
+ std::string _subgraph_name;
+ std::vector<const ::circle::OperatorCode *> _op_codes;
+ std::vector<int32_t> _inputs;
+ std::vector<int32_t> _outputs;
+ ::circle::DataFormat _data_format = ::circle::DataFormat::DataFormat_CHANNELS_FIRST;
+};
+
+} // namespace circle
+} // namespace mio
+
+#endif // __MIO_CIRCLE06_READER_H__
diff --git a/compiler/mio-circle06/src/Helper.cpp b/compiler/mio-circle06/src/Helper.cpp
new file mode 100644
index 000000000..bbfa2041a
--- /dev/null
+++ b/compiler/mio-circle06/src/Helper.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mio_circle/Helper.h"
+
+#include <algorithm>
+#include <sstream>
+
+namespace mio
+{
+namespace circle
+{
+
+/**
+ * This will provide v3/v3a/v3b format neutral BuiltinOperator
+ * NOTE circle has minus value opcode (252~254 as uint8_t)
+ * we cannot use std::max() like tflite as deprecated_builtin_code can be
+ * minus and builtin_code being 0 for v0.3 files.
+ */
+::circle::BuiltinOperator builtin_code_neutral(const ::circle::OperatorCode *opcode)
+{
+ assert(opcode != nullptr);
+ if (opcode->deprecated_builtin_code() == 127)
+ {
+ assert(opcode->builtin_code() >= 127);
+ return opcode->builtin_code();
+ }
+ // There was no 255(-1) value in v0.3
+ assert(opcode->deprecated_builtin_code() != -1);
+ return static_cast<::circle::BuiltinOperator>(opcode->deprecated_builtin_code());
+}
+
+bool is_valid(const ::circle::OperatorCode *opcode)
+{
+ // Valid Range : BuiltinOperator_MIN <= deprecated_builtin_code <= 127
+ const int8_t deprecated_builtin_code = opcode->deprecated_builtin_code();
+ if (deprecated_builtin_code < ::circle::BuiltinOperator_MIN)
+ return false;
+ // There was no 255(-1) value in v0.3
+ if (deprecated_builtin_code == -1)
+ return false;
+
+ const ::circle::BuiltinOperator builtin_code = opcode->builtin_code();
+ if (!(::circle::BuiltinOperator_MIN <= builtin_code &&
+ builtin_code <= ::circle::BuiltinOperator_MAX))
+ return false;
+
+ return true;
+}
+
+bool is_custom(const ::circle::OperatorCode *opcode)
+{
+ ::circle::BuiltinOperator code = builtin_code_neutral(opcode);
+ return (code == ::circle::BuiltinOperator_CUSTOM);
+}
+
+std::string opcode_name(const ::circle::OperatorCode *opcode)
+{
+ assert(opcode);
+
+ if (!is_valid(opcode))
+ {
+ std::ostringstream oss;
+ oss << "(invalid)";
+ return oss.str();
+ }
+
+ if (is_custom(opcode))
+ {
+ if (!opcode->custom_code())
+ return "(invalid custom)";
+
+ std::string custom_op = "CUSTOM(";
+ custom_op += opcode->custom_code()->c_str();
+ custom_op += ")";
+ return custom_op;
+ }
+
+ ::circle::BuiltinOperator code = builtin_code_neutral(opcode);
+ return ::circle::EnumNameBuiltinOperator(code);
+}
+
+const char *tensor_type(const ::circle::Tensor *tensor)
+{
+ return ::circle::EnumNameTensorType(tensor->type());
+}
+
+const char *tensor_name(const ::circle::Tensor *tensor)
+{
+ if (tensor->name() == nullptr || std::string(tensor->name()->c_str()).empty())
+ return "(noname)";
+
+ return tensor->name()->c_str();
+}
+
+} // namespace circle
+} // namespace mio
diff --git a/compiler/mio-circle06/src/Helper.test.cpp b/compiler/mio-circle06/src/Helper.test.cpp
new file mode 100644
index 000000000..9b158d198
--- /dev/null
+++ b/compiler/mio-circle06/src/Helper.test.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mio_circle/Helper.h"
+
+#include <flatbuffers/flatbuffers.h>
+#include <gtest/gtest.h>
+
+#include <vector>
+
+class mio_circle06_helper_test : public ::testing::Test
+{
+protected:
+ void initialization_finish(void)
+ {
+ _fbb.Finish(circle::CreateModelDirect(_fbb, 0, &_opcodes_vec));
+ }
+
+protected:
+ void add_operator_code(int8_t deprecated_builtin_code, const char *custom_code,
+ circle::BuiltinOperator builtin_code)
+ {
+ _opcodes_vec.push_back(circle::CreateOperatorCodeDirect(
+ _fbb, deprecated_builtin_code, custom_code, 1 /* version */, builtin_code));
+ }
+
+ const circle::OperatorCode *get_operator_code(uint8_t idx)
+ {
+ return circle::GetModel(_fbb.GetBufferPointer())->operator_codes()->Get(idx);
+ }
+
+private:
+ flatbuffers::FlatBufferBuilder _fbb;
+ std::vector<flatbuffers::Offset<circle::OperatorCode>> _opcodes_vec;
+};
+
+TEST_F(mio_circle06_helper_test, v06)
+{
+ // BuiltinOperator_ADD = 0
+ // BuiltinOperator_CONV_2D = 3
+ add_operator_code(3, "", circle::BuiltinOperator_ADD);
+ initialization_finish();
+
+ ASSERT_TRUE(mio::circle::is_valid(get_operator_code(0)));
+ ASSERT_EQ(mio::circle::builtin_code_neutral(get_operator_code(0)),
+ circle::BuiltinOperator_CONV_2D);
+ ASSERT_FALSE(mio::circle::is_custom(get_operator_code(0)));
+}
+
+TEST_F(mio_circle06_helper_test, v06_custom_old)
+{
+ // BuiltinOperator_ADD = 0
+ // BuiltinOperator_CUSTOM = 32
+ add_operator_code(32, "custom", circle::BuiltinOperator_ADD);
+ initialization_finish();
+
+ ASSERT_TRUE(mio::circle::is_valid(get_operator_code(0)));
+ ASSERT_EQ(mio::circle::builtin_code_neutral(get_operator_code(0)),
+ circle::BuiltinOperator_CUSTOM);
+ ASSERT_TRUE(mio::circle::is_custom(get_operator_code(0)));
+}
+
+TEST_F(mio_circle06_helper_test, v06_NEG)
+{
+ // BuiltinOperator_ADD = 0
+ // BuiltinOperator_CUMSUM = 128
+ // deprecated_builtin_code cannot be negative value
+ add_operator_code(128, "", circle::BuiltinOperator_ADD);
+ initialization_finish();
+
+ ASSERT_FALSE(mio::circle::is_valid(get_operator_code(0)));
+}
+
+TEST_F(mio_circle06_helper_test, v06_under127)
+{
+ // BuiltinOperator_CONV_2D = 3
+ add_operator_code(3, "", circle::BuiltinOperator_CONV_2D);
+ initialization_finish();
+
+ ASSERT_TRUE(mio::circle::is_valid(get_operator_code(0)));
+ ASSERT_EQ(mio::circle::builtin_code_neutral(get_operator_code(0)),
+ circle::BuiltinOperator_CONV_2D);
+ ASSERT_FALSE(mio::circle::is_custom(get_operator_code(0)));
+}
+
+TEST_F(mio_circle06_helper_test, v06_under127_NEG)
+{
+ // BuiltinOperator_CONV_2D = 3
+ // BuiltinOperator_CUMSUM = 128
+ // deprecated_builtin_code cannot be negative value
+ add_operator_code(128, "", circle::BuiltinOperator_CONV_2D);
+ initialization_finish();
+
+ ASSERT_FALSE(mio::circle::is_valid(get_operator_code(0)));
+}
+
+TEST_F(mio_circle06_helper_test, v06_custom)
+{
+ // BuiltinOperator_CUSTOM = 32
+ add_operator_code(32, "custom", circle::BuiltinOperator_CUSTOM);
+ initialization_finish();
+
+ ASSERT_TRUE(mio::circle::is_valid(get_operator_code(0)));
+ ASSERT_EQ(mio::circle::builtin_code_neutral(get_operator_code(0)),
+ circle::BuiltinOperator_CUSTOM);
+ ASSERT_TRUE(mio::circle::is_custom(get_operator_code(0)));
+}
+
+TEST_F(mio_circle06_helper_test, v06_custom_NEG)
+{
+ // BuiltinOperator_CUMSUM = 128
+ // deprecated_builtin_code cannot be negative value
+ add_operator_code(128, "custom", circle::BuiltinOperator_CUSTOM);
+ initialization_finish();
+
+ ASSERT_FALSE(mio::circle::is_valid(get_operator_code(0)));
+}
+
+TEST_F(mio_circle06_helper_test, v06_over127)
+{
+ // BuiltinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES = 127
+ // BuiltinOperator_CUMSUM = 128
+ add_operator_code(127, "", circle::BuiltinOperator_CUMSUM);
+ initialization_finish();
+
+ ASSERT_TRUE(mio::circle::is_valid(get_operator_code(0)));
+ ASSERT_EQ(mio::circle::builtin_code_neutral(get_operator_code(0)),
+ circle::BuiltinOperator_CUMSUM);
+ ASSERT_FALSE(mio::circle::is_custom(get_operator_code(0)));
+}
+
+TEST_F(mio_circle06_helper_test, v06_over127_NEG)
+{
+ // BuiltinOperator_CUMSUM = 128
+ // deprecated_builtin_code cannot be negative value
+ add_operator_code(128, "", circle::BuiltinOperator_CUMSUM);
+ initialization_finish();
+
+ ASSERT_FALSE(mio::circle::is_valid(get_operator_code(0)));
+}
diff --git a/compiler/mio-circle06/src/Reader.cpp b/compiler/mio-circle06/src/Reader.cpp
new file mode 100644
index 000000000..0ee22db14
--- /dev/null
+++ b/compiler/mio-circle06/src/Reader.cpp
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mio_circle/Reader.h"
+#include "mio_circle/Helper.h"
+
+#include <sstream>
+#include <string>
+
+namespace mio
+{
+namespace circle
+{
+
+Reader::Reader(const ::circle::Model *model)
+{
+ if (model == nullptr)
+ {
+ throw std::runtime_error("Invalid model");
+ }
+
+ _version = model->version();
+ _subgraphs = model->subgraphs();
+ _buffers = model->buffers();
+ _metadata = model->metadata();
+ _signature_defs = model->signature_defs();
+
+ auto opcodes = model->operator_codes();
+ for (const ::circle::OperatorCode *opcode : *opcodes)
+ {
+ _op_codes.push_back(opcode);
+ }
+}
+
+size_t Reader::buffer_info(uint32_t buf_idx, const uint8_t **buff_data)
+{
+ if (buff_data != nullptr)
+ {
+ *buff_data = nullptr;
+ }
+
+ if (buf_idx == 0)
+ return 0;
+
+ if (auto *buffer = (*_buffers)[buf_idx])
+ {
+ if (auto *array = buffer->data())
+ {
+ if (size_t size = array->size())
+ {
+ if (buff_data != nullptr)
+ {
+ *buff_data = reinterpret_cast<const uint8_t *>(array->data());
+ }
+ return size;
+ }
+ }
+ }
+
+ return 0;
+}
+
+::circle::BuiltinOperator Reader::builtin_code(const ::circle::Operator *op) const
+{
+ uint32_t index = op->opcode_index();
+ assert(index < _op_codes.size());
+ const ::circle::OperatorCode *opcode = _op_codes.at(index);
+
+ return mio::circle::builtin_code_neutral(opcode);
+}
+
+std::string Reader::opcode_name(const ::circle::Operator *op) const
+{
+ uint32_t index = op->opcode_index();
+ assert(index < _op_codes.size());
+ const ::circle::OperatorCode *opcode = _op_codes.at(index);
+
+ if (!mio::circle::is_valid(opcode))
+ {
+ std::ostringstream oss;
+ oss << "(invalid: " << index << ")";
+ return oss.str();
+ }
+
+ return mio::circle::opcode_name(opcode);
+}
+
+std::vector<int32_t> Reader::outputs(const ::circle::Operator *op) const
+{
+ return as_index_vector(op->outputs());
+}
+
+std::string Reader::tensor_name(const ::circle::Tensor *tensor) const
+{
+ return mio::circle::tensor_name(tensor);
+}
+
+std::string Reader::tensor_dtype(const ::circle::Tensor *tensor) const
+{
+ return mio::circle::tensor_type(tensor);
+}
+
+bool Reader::select_subgraph(uint32_t sgindex)
+{
+ _subgraph_index = sgindex;
+ _tensors = nullptr;
+ _operators = nullptr;
+
+ _inputs.clear();
+ _outputs.clear();
+
+ if (_subgraphs->Length() <= sgindex)
+ {
+ assert(false);
+ return false;
+ }
+
+ const ::circle::SubGraph *subgraph = (*_subgraphs)[sgindex];
+
+ auto name = subgraph->name();
+ _subgraph_name = name ? name->c_str() : "(noname)";
+
+ _tensors = subgraph->tensors();
+ _operators = subgraph->operators();
+ _data_format = subgraph->data_format();
+
+ _inputs = as_index_vector(subgraph->inputs());
+ _outputs = as_index_vector(subgraph->outputs());
+
+ return true;
+}
+
+} // namespace circle
+} // namespace mio
diff --git a/compiler/mio-circle06/src/Reader.test.cpp b/compiler/mio-circle06/src/Reader.test.cpp
new file mode 100644
index 000000000..668a8b1d9
--- /dev/null
+++ b/compiler/mio-circle06/src/Reader.test.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mio_circle/Reader.h"
+
+#include <flatbuffers/flatbuffers.h>
+#include <gtest/gtest.h>
+
+class mio_circle06_reader_test : public ::testing::Test
+{
+protected:
+ void initialization_emty(void)
+ {
+ _model = circle::CreateModelDirect(_fbb, 0, &_opcodes_vec);
+ circle::FinishModelBuffer(_fbb, _model);
+ }
+
+ const circle::Model *circleModel(void)
+ {
+ auto ptr = _fbb.GetBufferPointer();
+ return circle::GetModel(ptr);
+ }
+
+private:
+ flatbuffers::FlatBufferBuilder _fbb;
+ flatbuffers::Offset<circle::Model> _model;
+ std::vector<flatbuffers::Offset<circle::OperatorCode>> _opcodes_vec;
+};
+
+TEST_F(mio_circle06_reader_test, null_Model_NEG)
+{
+ EXPECT_THROW(mio::circle::Reader reader(nullptr), std::runtime_error);
+}
+
+TEST_F(mio_circle06_reader_test, empty_Model)
+{
+ initialization_emty();
+
+ const circle::Model *model = circleModel();
+ EXPECT_NE(nullptr, model);
+
+ mio::circle::Reader reader(model);
+
+ SUCCEED();
+}
+
+// TODO add more tests
diff --git a/compiler/mio-tflite2121/CMakeLists.txt b/compiler/mio-tflite2121/CMakeLists.txt
new file mode 100644
index 000000000..1ca8e7581
--- /dev/null
+++ b/compiler/mio-tflite2121/CMakeLists.txt
@@ -0,0 +1,60 @@
+nnas_find_package(FlatBuffers EXACT 2.0 QUIET)
+
+if(NOT FlatBuffers_FOUND)
+ message(STATUS "Build mio-tflite2121: FAILED (missing Flatbuffers 2.0)")
+ return()
+endif(NOT FlatBuffers_FOUND)
+
+nnas_find_package(TensorFlowSource EXACT 2.12.1 QUIET)
+
+if(NOT TensorFlowSource_FOUND)
+ message(STATUS "Build mio-tflite2121: FAILED (missing TensorFlowSource 2.12.1)")
+ return()
+endif(NOT TensorFlowSource_FOUND)
+
+message(STATUS "Build mio-tflite2121: TRUE")
+message(STATUS "Build mio-tflite2121: with ${TensorFlowSource_DIR}")
+
+set(SCHEMA_FILE "${TensorFlowSource_DIR}/tensorflow/lite/schema/schema.fbs")
+
+# NOTE Use copy of schema.fbs as to provide unified way for circle also
+add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/schema.fbs"
+ COMMAND ${CMAKE_COMMAND} -E copy "${SCHEMA_FILE}" schema.fbs
+ WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
+ DEPENDS "${SCHEMA_FILE}"
+)
+
+FlatBuffers_Target(mio_tflite2121
+ OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/gen/mio/tflite"
+ INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/gen"
+ SCHEMA_DIR "${CMAKE_CURRENT_BINARY_DIR}"
+ SCHEMA_FILES "schema.fbs"
+)
+
+add_executable(mio_tflite2121_example example.cpp)
+target_link_libraries(mio_tflite2121_example mio_tflite2121)
+
+# Temporay tflite validation tool to replace nnkit-tflite
+# TODO provide full tflite validation with runtime/interpreter
+add_executable(mio_tflite2121_validate example.cpp)
+target_link_libraries(mio_tflite2121_validate mio_tflite2121)
+
+file(GLOB_RECURSE SOURCES "src/*.cpp")
+file(GLOB_RECURSE TESTS "src/*.test.cpp")
+list(REMOVE_ITEM SOURCES ${TESTS})
+
+add_library(mio_tflite2121_helper STATIC ${SOURCES})
+target_include_directories(mio_tflite2121_helper PRIVATE src)
+target_include_directories(mio_tflite2121_helper PUBLIC include)
+target_link_libraries(mio_tflite2121_helper mio_tflite2121)
+
+if(NOT ENABLE_TEST)
+ return()
+endif(NOT ENABLE_TEST)
+
+nnas_find_package(GTest REQUIRED)
+
+GTest_AddTest(mio_tflite2121_helper_test ${TESTS})
+target_include_directories(mio_tflite2121_helper_test PRIVATE src)
+target_link_libraries(mio_tflite2121_helper_test mio_tflite2121)
+target_link_libraries(mio_tflite2121_helper_test mio_tflite2121_helper)
diff --git a/compiler/mio-tflite2121/README.md b/compiler/mio-tflite2121/README.md
new file mode 100644
index 000000000..a922f304b
--- /dev/null
+++ b/compiler/mio-tflite2121/README.md
@@ -0,0 +1,3 @@
+# mio-tflite2121
+
+_mio-tflite2121_ provides a library to access TensorFlow lite model files with V2.12.1.
diff --git a/compiler/mio-tflite2121/example.cpp b/compiler/mio-tflite2121/example.cpp
new file mode 100644
index 000000000..54fe9e799
--- /dev/null
+++ b/compiler/mio-tflite2121/example.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//
+// This example shows how to include and use "mio-tflite2121"
+//
+#include <mio/tflite/schema_generated.h>
+
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+int main(int argc, char **argv)
+{
+ std::ifstream ifs(argv[1], std::ios_base::binary);
+ std::vector<char> buf(std::istreambuf_iterator<char>{ifs}, std::istreambuf_iterator<char>{});
+
+ flatbuffers::Verifier verifier{reinterpret_cast<uint8_t *>(buf.data()), buf.size()};
+
+ if (!tflite::VerifyModelBuffer(verifier))
+ {
+ std::cout << "Fail" << std::endl;
+ return 255;
+ }
+
+ std::cout << "Pass" << std::endl;
+ return 0;
+}
diff --git a/compiler/mio-tflite2121/include/mio_tflite2121/Helper.h b/compiler/mio-tflite2121/include/mio_tflite2121/Helper.h
new file mode 100644
index 000000000..f2062600a
--- /dev/null
+++ b/compiler/mio-tflite2121/include/mio_tflite2121/Helper.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MIO_TFLITE2121_HELPER_H__
+#define __MIO_TFLITE2121_HELPER_H__
+
+#include <mio/tflite/schema_generated.h>
+
+namespace mio
+{
+namespace tflite
+{
+
+::tflite::BuiltinOperator builtin_code_neutral(const ::tflite::OperatorCode *opcode);
+bool is_valid(const ::tflite::OperatorCode *opcode);
+bool is_custom(const ::tflite::OperatorCode *opcode);
+std::string opcode_name(const ::tflite::OperatorCode *opcode);
+const char *tensor_type(const ::tflite::Tensor *tensor);
+const char *tensor_name(const ::tflite::Tensor *tensor);
+
+} // namespace tflite
+} // namespace mio
+
+#endif // __MIO_TFLITE2121_HELPER_H__
diff --git a/compiler/mio-tflite2121/src/Helper.cpp b/compiler/mio-tflite2121/src/Helper.cpp
new file mode 100644
index 000000000..b0d1ba107
--- /dev/null
+++ b/compiler/mio-tflite2121/src/Helper.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2020 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mio_tflite2121/Helper.h"
+
+#include <sstream>
+
+namespace mio
+{
+namespace tflite
+{
+
+/**
+ * This will provide v3/v3a format neutral BuiltinOperator
+ *
+ * This function referenced
+ * https://github.com/tensorflow/tensorflow/blob/7d12007d7800d3714a02e05059f3ea602d1aec78/tensorflow/lite/schema/schema_utils.cc
+ */
+::tflite::BuiltinOperator builtin_code_neutral(const ::tflite::OperatorCode *opcode)
+{
+ assert(opcode != nullptr);
+ return std::max(opcode->builtin_code(),
+ static_cast<::tflite::BuiltinOperator>(opcode->deprecated_builtin_code()));
+}
+
+bool is_valid(const ::tflite::OperatorCode *opcode)
+{
+ // Valid Range : 0 <= deprecated_builtin_code <= 127
+ const int8_t deprecated_builtin_code = opcode->deprecated_builtin_code();
+ if (deprecated_builtin_code < 0)
+ return false;
+
+ const ::tflite::BuiltinOperator builtin_code = opcode->builtin_code();
+ if (!(::tflite::BuiltinOperator_MIN <= builtin_code &&
+ builtin_code <= ::tflite::BuiltinOperator_MAX))
+ return false;
+
+ return true;
+}
+
+bool is_custom(const ::tflite::OperatorCode *opcode)
+{
+ ::tflite::BuiltinOperator code = builtin_code_neutral(opcode);
+ return (code == ::tflite::BuiltinOperator_CUSTOM);
+}
+
+std::string opcode_name(const ::tflite::OperatorCode *opcode)
+{
+ assert(opcode);
+
+ if (!is_valid(opcode))
+ {
+ std::ostringstream oss;
+ oss << "(invalid)";
+ return oss.str();
+ }
+
+ if (is_custom(opcode))
+ {
+ if (!opcode->custom_code())
+ return "(invalid custom)";
+
+ std::string custom_op = "CUSTOM(";
+ custom_op += opcode->custom_code()->c_str();
+ custom_op += ")";
+ return custom_op;
+ }
+
+ ::tflite::BuiltinOperator code = builtin_code_neutral(opcode);
+ return ::tflite::EnumNameBuiltinOperator(code);
+}
+
+const char *tensor_type(const ::tflite::Tensor *tensor)
+{
+ return ::tflite::EnumNameTensorType(tensor->type());
+}
+
+const char *tensor_name(const ::tflite::Tensor *tensor)
+{
+ static const char *kEmptyTensorName = "(noname)";
+
+ auto name = tensor->name();
+ if (name)
+ return name->c_str();
+
+ return kEmptyTensorName;
+}
+
+} // namespace tflite
+} // namespace mio
diff --git a/compiler/mio-tflite2121/src/Helper.test.cpp b/compiler/mio-tflite2121/src/Helper.test.cpp
new file mode 100644
index 000000000..1527a4956
--- /dev/null
+++ b/compiler/mio-tflite2121/src/Helper.test.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mio_tflite2121/Helper.h"
+
+#include <flatbuffers/flatbuffers.h>
+#include <gtest/gtest.h>
+
+#include <vector>
+
+class mio_tflite2121_helper_test : public ::testing::Test
+{
+protected:
+ void initialization_finish(void)
+ {
+ _fbb.Finish(tflite::CreateModelDirect(_fbb, 0, &_opcodes_vec));
+ }
+
+protected:
+ void add_operator_code(int8_t deprecated_builtin_code, const char *custom_code,
+ tflite::BuiltinOperator builtin_code)
+ {
+ _opcodes_vec.push_back(tflite::CreateOperatorCodeDirect(
+ _fbb, deprecated_builtin_code, custom_code, 1 /* version */, builtin_code));
+ }
+
+ const tflite::OperatorCode *get_operator_code(uint8_t idx)
+ {
+ return tflite::GetModel(_fbb.GetBufferPointer())->operator_codes()->Get(idx);
+ }
+
+private:
+ flatbuffers::FlatBufferBuilder _fbb;
+ std::vector<flatbuffers::Offset<tflite::OperatorCode>> _opcodes_vec;
+};
+
+/**
+ * Extended 'builtin_code' is not in TFLite schema v3.
+ *
+ * Thus it is filled with 0(BuiltinOperator_ADD) in schame v3. Please refer to
+ * https://github.com/tensorflow/tensorflow/blob/1ab788fa8d08430be239ab970980b891ad7af494/tensorflow/lite/schema/schema_utils.cc#L28-L31
+ */
+TEST_F(mio_tflite2121_helper_test, v3)
+{
+ // BuiltinOperator_ADD = 0
+ // BuiltinOperator_CONV_2D = 3
+ add_operator_code(3, "", tflite::BuiltinOperator_ADD);
+ initialization_finish();
+
+ ASSERT_TRUE(mio::tflite::is_valid(get_operator_code(0)));
+ ASSERT_EQ(mio::tflite::builtin_code_neutral(get_operator_code(0)),
+ tflite::BuiltinOperator_CONV_2D);
+ ASSERT_FALSE(mio::tflite::is_custom(get_operator_code(0)));
+}
+
+TEST_F(mio_tflite2121_helper_test, v3_custom)
+{
+ // BuiltinOperator_ADD = 0
+ // BuiltinOperator_CUSTOM = 32
+ add_operator_code(32, "custom", tflite::BuiltinOperator_ADD);
+ initialization_finish();
+
+ ASSERT_TRUE(mio::tflite::is_valid(get_operator_code(0)));
+ ASSERT_EQ(mio::tflite::builtin_code_neutral(get_operator_code(0)),
+ tflite::BuiltinOperator_CUSTOM);
+ ASSERT_TRUE(mio::tflite::is_custom(get_operator_code(0)));
+}
+
+TEST_F(mio_tflite2121_helper_test, v3_NEG)
+{
+ // BuiltinOperator_ADD = 0
+ // BuiltinOperator_CUMSUM = 128
+ // deprecated_builtin_code cannot be negative value
+ add_operator_code(128, "", tflite::BuiltinOperator_ADD);
+ initialization_finish();
+
+ ASSERT_FALSE(mio::tflite::is_valid(get_operator_code(0)));
+}
+
+TEST_F(mio_tflite2121_helper_test, v3a_under127)
+{
+ // BuiltinOperator_CONV_2D = 3
+ add_operator_code(3, "", tflite::BuiltinOperator_CONV_2D);
+ initialization_finish();
+
+ ASSERT_TRUE(mio::tflite::is_valid(get_operator_code(0)));
+ ASSERT_EQ(mio::tflite::builtin_code_neutral(get_operator_code(0)),
+ tflite::BuiltinOperator_CONV_2D);
+ ASSERT_FALSE(mio::tflite::is_custom(get_operator_code(0)));
+}
+
+TEST_F(mio_tflite2121_helper_test, v3a_under127_NEG)
+{
+ // BuiltinOperator_CONV_2D = 3
+ // BuiltinOperator_CUMSUM = 128
+ // deprecated_builtin_code cannot be negative value
+ add_operator_code(128, "", tflite::BuiltinOperator_CONV_2D);
+ initialization_finish();
+
+ ASSERT_FALSE(mio::tflite::is_valid(get_operator_code(0)));
+}
+
+TEST_F(mio_tflite2121_helper_test, v3a_custom)
+{
+ // BuiltinOperator_CUSTOM = 32
+ add_operator_code(32, "custom", tflite::BuiltinOperator_CUSTOM);
+ initialization_finish();
+
+ ASSERT_TRUE(mio::tflite::is_valid(get_operator_code(0)));
+ ASSERT_EQ(mio::tflite::builtin_code_neutral(get_operator_code(0)),
+ tflite::BuiltinOperator_CUSTOM);
+ ASSERT_TRUE(mio::tflite::is_custom(get_operator_code(0)));
+}
+
+TEST_F(mio_tflite2121_helper_test, v3a_custom_NEG)
+{
+ // BuiltinOperator_CUMSUM = 128
+ // deprecated_builtin_code cannot be negative value
+ add_operator_code(128, "custom", tflite::BuiltinOperator_CUSTOM);
+ initialization_finish();
+
+ ASSERT_FALSE(mio::tflite::is_valid(get_operator_code(0)));
+}
+
+TEST_F(mio_tflite2121_helper_test, v3a_over127)
+{
+ // BuiltinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES = 127
+ // BuiltinOperator_CUMSUM = 128
+ add_operator_code(127, "", tflite::BuiltinOperator_CUMSUM);
+ initialization_finish();
+
+ ASSERT_TRUE(mio::tflite::is_valid(get_operator_code(0)));
+ ASSERT_EQ(mio::tflite::builtin_code_neutral(get_operator_code(0)),
+ tflite::BuiltinOperator_CUMSUM);
+ ASSERT_FALSE(mio::tflite::is_custom(get_operator_code(0)));
+}
+
+TEST_F(mio_tflite2121_helper_test, v3a_over127_NEG)
+{
+ // BuiltinOperator_CUMSUM = 128
+ // deprecated_builtin_code cannot be negative value
+ add_operator_code(128, "", tflite::BuiltinOperator_CUMSUM);
+ initialization_finish();
+
+ ASSERT_FALSE(mio::tflite::is_valid(get_operator_code(0)));
+}
diff --git a/compiler/mir/unittests/ShapeRange.cpp b/compiler/mir/unittests/ShapeRange.cpp
index 3797e3ccc..91b1be744 100644
--- a/compiler/mir/unittests/ShapeRange.cpp
+++ b/compiler/mir/unittests/ShapeRange.cpp
@@ -56,7 +56,7 @@ TEST_P(ShapeIteratorTest, ElementCount)
std::vector<ParamType> test_data{ParamType{6, 1, 2, 3}, ParamType{16, 2, 2, 4},
ParamType{1, 1, 1, 1, 1, 1}, ParamType{5, 5, 1, 1, 1, 1, 1}};
-INSTANTIATE_TEST_CASE_P(SimpleInput, ShapeIteratorTest, ::testing::ValuesIn(test_data));
+INSTANTIATE_TEST_SUITE_P(SimpleInput, ShapeIteratorTest, ::testing::ValuesIn(test_data));
TEST(ShapeRange, Contains)
{
diff --git a/compiler/moco-tf/src/Canonicalization/SoftmaxCanonicalizer.h b/compiler/moco-tf/src/Canonicalization/SoftmaxCanonicalizer.h
index 0dd31503f..33fc14a6d 100644
--- a/compiler/moco-tf/src/Canonicalization/SoftmaxCanonicalizer.h
+++ b/compiler/moco-tf/src/Canonicalization/SoftmaxCanonicalizer.h
@@ -15,7 +15,7 @@
*/
#ifndef __MOCO_TF_SOFTMAX_CANONICALIZER_H__
-#define __MOCO_TF_SOFTMAx_CANONICALIZER_H__
+#define __MOCO_TF_SOFTMAX_CANONICALIZER_H__
#include "Transform.h"
#include "SimpleNodeTransform.h"
diff --git a/compiler/nnc/backends/soft_backend/code_snippets/cpp_header_types.def b/compiler/nnc/backends/soft_backend/code_snippets/cpp_header_types.def
index 771329cdd..db46a1e97 100644
--- a/compiler/nnc/backends/soft_backend/code_snippets/cpp_header_types.def
+++ b/compiler/nnc/backends/soft_backend/code_snippets/cpp_header_types.def
@@ -147,7 +147,7 @@ public:
if (!t._managed) {
if (_managed)
- delete _data;
+ delete [] _data;
_managed = false;
_data = t._data;
diff --git a/compiler/nnc/backends/soft_backend/code_snippets/eigen.def b/compiler/nnc/backends/soft_backend/code_snippets/eigen.def
index b02f84bed..b6547d5a6 100644
--- a/compiler/nnc/backends/soft_backend/code_snippets/eigen.def
+++ b/compiler/nnc/backends/soft_backend/code_snippets/eigen.def
@@ -13381,7 +13381,7 @@ struct palign_impl<Offset,Type>\
if (Offset!=0)\
first = Command(first, second, Offset);\
}\
-};\
+};
PALIGN_NEON(0,Packet2d,vextq_f64)
PALIGN_NEON(1,Packet2d,vextq_f64)
#undef PALIGN_NEON
diff --git a/compiler/one-cmds/CMakeLists.txt b/compiler/one-cmds/CMakeLists.txt
index 7772b5340..917bbdaf6 100644
--- a/compiler/one-cmds/CMakeLists.txt
+++ b/compiler/one-cmds/CMakeLists.txt
@@ -36,13 +36,19 @@ set(ONE_COMMAND_FILES
)
# TODO find better way for per-platform files
-if(ONE_UBUNTU_CODENAME_JAMMY)
- # NOTE copy one-prepare-venv.u2204 as build/../one-prepare-venv
+if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "aarch64")
+ # NOTE copy one-prepare-venv.aarch64 as build/../one-prepare-venv
# and install build/../one-prepare-venv file
- list(APPEND ONE_COMMAND_FILES one-prepare-venv.u2204)
-else()
- list(APPEND ONE_COMMAND_FILES one-prepare-venv)
-endif()
+ list(APPEND ONE_COMMAND_FILES one-prepare-venv.aarch64)
+else(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "aarch64")
+ if(ONE_UBUNTU_CODENAME_BIONIC)
+ # NOTE copy one-prepare-venv.u1804 as build/../one-prepare-venv
+ # and install build/../one-prepare-venv file
+ list(APPEND ONE_COMMAND_FILES one-prepare-venv.u1804)
+ else(ONE_UBUNTU_CODENAME_BIONIC)
+ list(APPEND ONE_COMMAND_FILES one-prepare-venv)
+ endif(ONE_UBUNTU_CODENAME_BIONIC)
+endif(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "aarch64")
# pytorch importer is an experimental feature, it is not used in default configuration
if(ENABLE_ONE_IMPORT_PYTORCH)
@@ -113,7 +119,8 @@ install(FILES ${MODEL2NNPKG}
RENAME "model2nnpkg")
# make python directory
-set(ONE_PYTHON_FILES constant.py
+set(ONE_PYTHON_FILES backends.py
+ constant.py
export_constant.py
make_cmd.py
CfgRunner.py
diff --git a/compiler/one-cmds/dummy-driver/CMakeLists.txt b/compiler/one-cmds/dummy-driver/CMakeLists.txt
index 912798e36..55ef96c06 100644
--- a/compiler/one-cmds/dummy-driver/CMakeLists.txt
+++ b/compiler/one-cmds/dummy-driver/CMakeLists.txt
@@ -1,30 +1,42 @@
# dummy driver for interface test
set(DUMMY_DRIVER_SRC src/dummy-compile.cpp)
+set(DUMMY_V2_DRIVER_SRC src/dummyV2-compile.cpp)
set(HELP_DRIVER_SRC src/help-compile.cpp)
set(DUMMY_INFER_SRC src/dummy-infer.cpp)
set(DUMMY_INFER_V2_SRC src/dummy-inferV2.cpp)
set(HELP_INFER_SRC src/help-infer.cpp)
set(DUMMY_PROFILE_SRC src/dummy-profile.cpp)
+set(DUMMY_V2_PROFILE_SRC src/dummyV2-profile.cpp)
+set(DUMMY_V3_PROFILE_SRC src/dummyV3-profile.cpp)
set(HELP_PROFILE_SRC src/help-profile.cpp)
set(DUMMY_ENV_SRC src/dummyEnv-compile.cpp)
+set(DUMMY_ONNX_EXT src/dummy-onnx-ext.cpp)
add_executable(dummy-compile ${DUMMY_DRIVER_SRC})
+add_executable(dummyV2-compile ${DUMMY_V2_DRIVER_SRC})
add_executable(help-compile ${HELP_DRIVER_SRC})
add_executable(dummy-infer ${DUMMY_INFER_SRC})
add_executable(dummy-inferV2 ${DUMMY_INFER_V2_SRC})
add_executable(help-infer ${HELP_INFER_SRC})
add_executable(dummy-profile ${DUMMY_PROFILE_SRC})
+add_executable(dummyV2-profile ${DUMMY_V2_PROFILE_SRC})
+add_executable(dummyV3-profile ${DUMMY_V3_PROFILE_SRC})
add_executable(help-profile ${HELP_PROFILE_SRC})
add_executable(dummyEnv-compile ${DUMMY_ENV_SRC})
+add_executable(dummy-onnx-ext ${DUMMY_ONNX_EXT})
set(DUMMY_DRIVER "${CMAKE_CURRENT_BINARY_DIR}/dummy-compile")
+set(DUMMY_V2_DRIVER "${CMAKE_CURRENT_BINARY_DIR}/dummyV2-compile")
set(HELP_DRIVER "${CMAKE_CURRENT_BINARY_DIR}/help-compile")
set(DUMMY_INFER "${CMAKE_CURRENT_BINARY_DIR}/dummy-infer")
set(DUMMY_INFER_V2 "${CMAKE_CURRENT_BINARY_DIR}/dummy-inferV2")
set(HELP_INFER "${CMAKE_CURRENT_BINARY_DIR}/help-infer")
set(DUMMY_PROFILE "${CMAKE_CURRENT_BINARY_DIR}/dummy-profile")
+set(DUMMY_V2_PROFILE "${CMAKE_CURRENT_BINARY_DIR}/dummyV2-profile")
+set(DUMMY_V3_PROFILE "${CMAKE_CURRENT_BINARY_DIR}/dummyV3-profile")
set(HELP_PROFILE "${CMAKE_CURRENT_BINARY_DIR}/help-profile")
set(DUMMY_ENV "${CMAKE_CURRENT_BINARY_DIR}/dummyEnv-compile")
+set(DUMMY_ONNX_EXT "${CMAKE_CURRENT_BINARY_DIR}/dummy-onnx-ext")
install(FILES ${DUMMY_DRIVER}
PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE
@@ -32,6 +44,12 @@ install(FILES ${DUMMY_DRIVER}
WORLD_READ WORLD_EXECUTE
DESTINATION test)
+install(FILES ${DUMMY_V2_DRIVER}
+ PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE
+ DESTINATION test)
+
install(FILES ${HELP_DRIVER}
PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE
GROUP_READ GROUP_EXECUTE
@@ -62,6 +80,18 @@ install(FILES ${DUMMY_PROFILE}
WORLD_READ WORLD_EXECUTE
DESTINATION test)
+install(FILES ${DUMMY_V2_PROFILE}
+ PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE
+ DESTINATION test)
+
+install(FILES ${DUMMY_V3_PROFILE}
+ PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE
+ DESTINATION test)
+
install(FILES ${HELP_PROFILE}
PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE
GROUP_READ GROUP_EXECUTE
@@ -73,3 +103,9 @@ install(FILES ${DUMMY_ENV}
GROUP_READ GROUP_EXECUTE
WORLD_READ WORLD_EXECUTE
DESTINATION test)
+
+install(FILES ${DUMMY_ONNX_EXT}
+ PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE
+ DESTINATION test)
diff --git a/compiler/circle-mpqsolver/src/bisection/ErrorApproximator.h b/compiler/one-cmds/dummy-driver/src/dummy-onnx-ext.cpp
index efbfa8261..845445bf5 100644
--- a/compiler/circle-mpqsolver/src/bisection/ErrorApproximator.h
+++ b/compiler/one-cmds/dummy-driver/src/dummy-onnx-ext.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,24 +14,23 @@
* limitations under the License.
*/
-#ifndef __MPQSOLVER_BISECTION_ERROR_APPROXIMATOR_H__
-#define __MPQSOLVER_BISECTION_ERROR_APPROXIMATOR_H__
-
-#include <loco.h>
+/**
+ * dummy-onnx-ext only tests its interface rather than its functionality.
+ *
+ * ./dummy-onnx-ext [options]
+ * one-import-onnx-ext dummy output!!!
+ */
-#include <luci/IR/CircleNodeDecl.h>
+#include <iostream>
+#include <fstream>
+#include <string>
-namespace mpqsolver
+int main(int argc, char **argv)
{
-namespace bisection
-{
-
-/**
- * @brief approximate error introduced while quantizing node into Q8
- */
-float approximate(const luci::CircleNode *node);
+ (void)argc;
+ (void)argv;
-} // namespace bisection
-} // namespace mpqsolver
+ std::cout << "one-import-onnx-ext dummy output!!!" << std::endl;
-#endif // __MPQSOLVER_BISECTION_ERROR_APPROXIMATOR_H__
+ return EXIT_SUCCESS;
+}
diff --git a/compiler/one-cmds/dummy-driver/src/dummyV2-compile.cpp b/compiler/one-cmds/dummy-driver/src/dummyV2-compile.cpp
new file mode 100644
index 000000000..bc7372e2e
--- /dev/null
+++ b/compiler/one-cmds/dummy-driver/src/dummyV2-compile.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * dummyV2-compile only tests its interface rather than its functionality.
+ *
+ * ./dummyV2-compile -o ${OUTPUT_NAME} ${INPUT_NAME}
+ *
+ * NOTE argv[3](INPUT_NAME) is not used here.
+ */
+
+#include <iostream>
+#include <fstream>
+#include <string>
+
+int main(int argc, char **argv)
+{
+ if (argc != 4)
+ return EXIT_FAILURE;
+
+ std::string opt_o{"-O"};
+ std::string argv_1{argv[1]};
+
+ if (opt_o != argv_1)
+ {
+ std::cout << "dummyV2-compile: Invalid option" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ std::string output_name{argv[2]};
+ std::ofstream outfile(output_name);
+
+ outfile << "dummyV2-compile dummy output!!" << std::endl;
+
+ outfile.close();
+
+ return EXIT_SUCCESS;
+}
diff --git a/compiler/one-cmds/dummy-driver/src/dummyV2-profile.cpp b/compiler/one-cmds/dummy-driver/src/dummyV2-profile.cpp
new file mode 100644
index 000000000..020f320d9
--- /dev/null
+++ b/compiler/one-cmds/dummy-driver/src/dummyV2-profile.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * dummyV2-profile only tests its interface rather than its functionality.
+ *
+ * ./dummyV2-profile ${INPUT_NAME}
+ * dummyV2-profile dummy output!!!
+ */
+
+#include <iostream>
+#include <fstream>
+#include <string>
+
+int main(int argc, char **argv)
+{
+ if (argc != 2)
+ return EXIT_FAILURE;
+
+ std::cout << "dummyV2-profile dummy output!!!" << std::endl;
+
+ return EXIT_SUCCESS;
+}
diff --git a/compiler/one-cmds/dummy-driver/src/dummyV3-profile.cpp b/compiler/one-cmds/dummy-driver/src/dummyV3-profile.cpp
new file mode 100644
index 000000000..d10644696
--- /dev/null
+++ b/compiler/one-cmds/dummy-driver/src/dummyV3-profile.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * dummyV3-profile only tests its interface rather than its functionality.
+ *
+ * ./dummyV3-profile ${INPUT_TO_PRINT}
+ * dummyV3-profile with ${INPUT_TO_PRINT}
+ */
+
+#include <iostream>
+#include <fstream>
+#include <string>
+
+int main(int argc, char **argv)
+{
+ if (argc != 2)
+ return EXIT_FAILURE;
+
+ std::string input_to_print{argv[1]};
+
+ std::cout << "dummyV3-profile with " << input_to_print << std::endl;
+
+ return EXIT_SUCCESS;
+}
diff --git a/compiler/one-cmds/one-codegen b/compiler/one-cmds/one-codegen
index 5ccff0f93..a956a63e2 100644
--- a/compiler/one-cmds/one-codegen
+++ b/compiler/one-cmds/one-codegen
@@ -27,53 +27,15 @@ import ntpath
import os
import sys
import shutil
+from types import SimpleNamespace
+import onelib.backends as backends
import onelib.utils as oneutils
# TODO Find better way to suppress trackback on error
sys.tracebacklimit = 0
-def _get_backends_list():
- """
- [one hierarchy]
- one
- ├── backends
- ├── bin
- ├── doc
- ├── include
- ├── lib
- └── test
-
- The list where `one-codegen` finds its backends
- - `bin` folder where `one-codegen` exists
- - `backends` folder
- - System path
-
- NOTE If there are backends of the same name in different places,
- the closer to the top in the list, the higher the priority.
- """
- dir_path = os.path.dirname(os.path.realpath(__file__))
- backend_set = set()
-
- # bin folder
- files = [f for f in glob.glob(dir_path + '/*-compile')]
- # backends folder
- files += [
- f for f in glob.glob(dir_path + '/../backends/**/*-compile', recursive=True)
- ]
- # TODO find backends in `$PATH`
-
- backends_list = []
- for cand in files:
- base = ntpath.basename(cand)
- if not base in backend_set and os.path.isfile(cand) and os.access(cand, os.X_OK):
- backend_set.add(base)
- backends_list.append(cand)
-
- return backends_list
-
-
def _get_parser(backends_list):
codegen_usage = 'one-codegen [-h] [-v] [-C CONFIG] [-b BACKEND] [--] [COMMANDS FOR BACKEND]'
parser = argparse.ArgumentParser(
@@ -94,15 +56,47 @@ def _get_parser(backends_list):
return parser
-def _verify_arg(parser, args):
+def _verify_arg(parser, args, cfg_args, backend_args, unknown_args):
"""verify given arguments"""
+ cmd_backend_exist = oneutils.is_valid_attr(args, 'backend')
+ cfg_backend_exist = oneutils.is_valid_attr(cfg_args, 'backend')
+ cfg_backends_exist = oneutils.is_valid_attr(cfg_args, 'backends')
+
# check if required arguments is given
missing = []
- if not oneutils.is_valid_attr(args, 'backend'):
+ if not cmd_backend_exist and not cfg_backend_exist and not cfg_backends_exist:
missing.append('-b/--backend')
if len(missing):
parser.error('the following arguments are required: ' + ' '.join(missing))
+ if not oneutils.is_valid_attr(args, 'config'):
+ if not backend_args and not unknown_args:
+ parser.error('commands for the backend is missing.')
+
+ if cfg_backend_exist and cfg_backends_exist:
+ parser.error(
+ '\'backend\' option and \'backends\' option cannot be used simultaneously.')
+
+ # Check if given backend from command line exists in the configuration file
+ if cmd_backend_exist and cfg_backend_exist:
+ if args.backend != cfg_args.backend:
+ parser.error('Not found the command of given backend')
+
+ if cfg_backend_exist and not oneutils.is_valid_attr(cfg_args, 'command'):
+ parser.error('\'command\' key is missing in the configuration file.')
+
+ if cfg_backends_exist:
+ cfg_backends = getattr(cfg_args, 'backends').split(',')
+ # check if commands of given backends exist
+ for b in cfg_backends:
+ if not oneutils.is_valid_attr(cfg_args, b):
+ parser.error('Not found the command for ' + b)
+
+ # Check if given backend from command line exists in the configuration file
+ if cmd_backend_exist:
+ if args.backend not in cfg_backends:
+ parser.error('Not found the command of given backend')
+
def _parse_arg(parser):
codegen_args = []
@@ -134,36 +128,89 @@ def _parse_arg(parser):
def main():
# get backend list
- backends_list = _get_backends_list()
+ backends_list = backends.get_list('compile')
# parse arguments
parser = _get_parser(backends_list)
args, backend_args, unknown_args = _parse_arg(parser)
# parse configuration file
- oneutils.parse_cfg(args.config, 'one-codegen', args)
+ cfg_args = SimpleNamespace()
+ oneutils.parse_cfg(args.config, 'one-codegen', cfg_args)
+
+ # parse configuration file (args has arguments parsed from command line + cfg)
+ # oneutils.parse_cfg(args.config, 'one-codegen', args)
# verify arguments
- _verify_arg(parser, args)
-
- # make a command to run given backend driver
- codegen_path = None
- backend_base = getattr(args, 'backend') + '-compile'
- for cand in backends_list:
- if ntpath.basename(cand) == backend_base:
- codegen_path = cand
- if not codegen_path:
- # Find backend from system path
- codegen_path = shutil.which(backend_base)
-
- if not codegen_path:
- raise FileNotFoundError(backend_base + ' not found')
- codegen_cmd = [codegen_path] + backend_args + unknown_args
- if oneutils.is_valid_attr(args, 'command'):
- codegen_cmd += getattr(args, 'command').split()
-
- # run backend driver
- oneutils.run(codegen_cmd, err_prefix=backend_base)
+ _verify_arg(parser, args, cfg_args, backend_args, unknown_args)
+ '''
+ one-codegen defines its behavior for below cases.
+
+ [1] one-codegen -h
+ [2] one-codegen -v
+ [3] one-codegen -C ${cfg} (backend, command key in cfg)
+ [4] one-codegen -C ${cfg} (backends key in cfg)
+ [5] one-codegen -b ${backend} ${command}
+ [6] one-codegen -b ${backend} -- ${command}
+ [7] one-codegen -b ${backend} -C {cfg} (backend, command key in cfg)
+ [8] one-codegen -b ${backend} -C {cfg} (backends key in cfg) (Only 'backend' is invoked,
+ even though cfg file has multiple backends)
+ [9] one-codegen -b ${backend} -C ${cfg} -- ${command} (backend, command key in cfg)
+ [10] one-codegen -b ${backend} -C ${cfg} -- ${command} (backends key in cfg) (Only 'backend' is invoked,
+ even though cfg file has multiple backends)
+
+ All other cases are not allowed or an undefined behavior.
+ '''
+ cmd_overwrite = False
+ if oneutils.is_valid_attr(args, 'config'):
+ # [9], [10]
+ if backend_args and not unknown_args:
+ given_backends = [args.backend]
+ cmd_overwrite = True
+ else:
+ # [7], [8]
+ if oneutils.is_valid_attr(args, 'backend'):
+ given_backends = [args.backend]
+ if oneutils.is_valid_attr(cfg_args, 'backend'):
+ assert (oneutils.is_valid_attr(cfg_args, 'command'))
+ setattr(cfg_args, args.backend, cfg_args.command)
+ else:
+ # [3]
+ if oneutils.is_valid_attr(cfg_args, 'backend'):
+ assert (oneutils.is_valid_attr(cfg_args, 'command'))
+ given_backends = [cfg_args.backend]
+ setattr(cfg_args, cfg_args.backend, cfg_args.command)
+ # [4]
+ if oneutils.is_valid_attr(cfg_args, 'backends'):
+ given_backends = cfg_args.backends.split(',')
+ # [5], [6]
+ else:
+ assert (backend_args or unknown_args)
+ given_backends = [args.backend]
+
+ for given_backend in given_backends:
+ # make a command to run given backend driver
+ codegen_path = None
+ backend_base = given_backend + '-compile'
+ for cand in backends_list:
+ if ntpath.basename(cand) == backend_base:
+ codegen_path = cand
+ if not codegen_path:
+ # Find backend from system path
+ codegen_path = shutil.which(backend_base)
+
+ if not codegen_path:
+ raise FileNotFoundError(backend_base + ' not found')
+
+ codegen_cmd = [codegen_path]
+ if not cmd_overwrite and oneutils.is_valid_attr(cfg_args, given_backend):
+ codegen_cmd += getattr(cfg_args, given_backend).split()
+ else:
+ codegen_cmd += backend_args
+ codegen_cmd += unknown_args
+
+ # run backend driver
+ oneutils.run(codegen_cmd, err_prefix=backend_base)
if __name__ == '__main__':
diff --git a/compiler/one-cmds/one-import-onnx b/compiler/one-cmds/one-import-onnx
index 24edea645..b9c773b06 100644
--- a/compiler/one-cmds/one-import-onnx
+++ b/compiler/one-cmds/one-import-onnx
@@ -41,6 +41,89 @@ import onelib.utils as oneutils
sys.tracebacklimit = 0
+# Class to rename input/output to prevent issues while import ONNX models
+class TidyIONames:
+ def __init__(self, onnx_model):
+ self.input_nodes = []
+ self.output_nodes = []
+ self.remap_inputs = []
+ self.remap_outputs = []
+ self.initializers = []
+ self.onnx_model = onnx_model
+ # some models may have initializers as inputs. ignore them.
+ for initializer in onnx_model.graph.initializer:
+ self.initializers.append(initializer.name)
+
+ def order(self):
+ for idx in range(0, len(self.onnx_model.graph.input)):
+ name = self.onnx_model.graph.input[idx].name
+ if not name in self.initializers:
+ self.input_nodes.append(name)
+ self.remap_inputs.append('i_' + format(idx + 1, '04d') + '_' + name)
+ for idx in range(0, len(self.onnx_model.graph.output)):
+ name = self.onnx_model.graph.output[idx].name
+ self.output_nodes.append(name)
+ self.remap_outputs.append('o_' + format(idx + 1, '04d') + '_' + name)
+
+ # exclude special characters in names
+ def sanitize(self):
+ for idx in range(0, len(self.onnx_model.graph.input)):
+ name = self.onnx_model.graph.input[idx].name
+ if not name in self.initializers:
+ if '.' in name or ':' in name or name[:1].isdigit():
+ self.input_nodes.append(name)
+ name_alt = name.replace('.', '_')
+ name_alt = name_alt.replace(':', '_')
+ if name_alt[:1].isdigit():
+ name_alt = 'a_' + name_alt
+ self.remap_inputs.append(name_alt)
+ for idx in range(0, len(self.onnx_model.graph.output)):
+ name = self.onnx_model.graph.output[idx].name
+ if '.' in name or ':' in name or name[:1].isdigit():
+ self.output_nodes.append(name)
+ name_alt = name.replace('.', '_')
+ name_alt = name_alt.replace(':', '_')
+ if name_alt[:1].isdigit():
+ name_alt = 'a_' + name_alt
+ self.remap_outputs.append(name_alt)
+
+ def update(self):
+ # change names for graph input
+ for i in range(len(self.onnx_model.graph.input)):
+ if self.onnx_model.graph.input[i].name in self.input_nodes:
+ to_rename = self.onnx_model.graph.input[i].name
+ idx = self.input_nodes.index(to_rename)
+ self.onnx_model.graph.input[i].name = self.remap_inputs[idx]
+ # change names of all nodes in the graph
+ for i in range(len(self.onnx_model.graph.node)):
+ # check node.input is to change to remap_inputs or remap_outputs
+ for j in range(len(self.onnx_model.graph.node[i].input)):
+ if self.onnx_model.graph.node[i].input[j] in self.input_nodes:
+ to_rename = self.onnx_model.graph.node[i].input[j]
+ idx = self.input_nodes.index(to_rename)
+ self.onnx_model.graph.node[i].input[j] = self.remap_inputs[idx]
+ if self.onnx_model.graph.node[i].input[j] in self.output_nodes:
+ to_rename = self.onnx_model.graph.node[i].input[j]
+ idx = self.output_nodes.index(to_rename)
+ self.onnx_model.graph.node[i].input[j] = self.remap_outputs[idx]
+ # check node.output is to change to remap_inputs or remap_outputs
+ for j in range(len(self.onnx_model.graph.node[i].output)):
+ if self.onnx_model.graph.node[i].output[j] in self.output_nodes:
+ to_rename = self.onnx_model.graph.node[i].output[j]
+ idx = self.output_nodes.index(to_rename)
+ self.onnx_model.graph.node[i].output[j] = self.remap_outputs[idx]
+ if self.onnx_model.graph.node[i].output[j] in self.input_nodes:
+ to_rename = self.onnx_model.graph.node[i].output[j]
+ idx = self.input_nodes.index(to_rename)
+ self.onnx_model.graph.node[i].output[j] = self.remap_inputs[idx]
+ # change names for graph output
+ for i in range(len(self.onnx_model.graph.output)):
+ if self.onnx_model.graph.output[i].name in self.output_nodes:
+ to_rename = self.onnx_model.graph.output[i].name
+ idx = self.output_nodes.index(to_rename)
+ self.onnx_model.graph.output[i].name = self.remap_outputs[idx]
+
+
def get_driver_cfg_section():
return "one-import-onnx"
@@ -135,63 +218,32 @@ def _apply_verbosity(verbosity):
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
+# TF2.12.1 tries to sanitize special characters, '.:' and maybe others and then fails with
+# 'IndexError: tuple index out of range' error from somewhere else.
+# This method is to prevent this IndexError.
+def _sanitize_io_names(onnx_model):
+ sanitizer = TidyIONames(onnx_model)
+ sanitizer.sanitize()
+ sanitizer.update()
+
+
# The index of input/output is added in front of the name. For example,
# Original input names: 'a', 'c', 'b'
-# Renamed: '0001_a', '0002_c', '0003_b'
+# Renamed: 'i_0001_a', 'i_0002_c', 'i_0003_b'
# This will preserve I/O order after import.
def _remap_io_names(onnx_model):
# gather existing name of I/O and generate new name of I/O in sort order
- input_nodes = []
- output_nodes = []
- remap_inputs = []
- remap_outputs = []
- initializers = []
- # some models may have initializers as inputs. ignore them.
- for initializer in onnx_model.graph.initializer:
- initializers.append(initializer.name)
- for idx in range(0, len(onnx_model.graph.input)):
- name = onnx_model.graph.input[idx].name
- if not name in initializers:
- input_nodes.append(name)
- remap_inputs.append(format(idx + 1, '04d') + '_' + name)
- for idx in range(0, len(onnx_model.graph.output)):
- name = onnx_model.graph.output[idx].name
- output_nodes.append(name)
- remap_outputs.append(format(idx + 1, '04d') + '_' + name)
- # change names for graph input
- for i in range(len(onnx_model.graph.input)):
- if onnx_model.graph.input[i].name in input_nodes:
- to_rename = onnx_model.graph.input[i].name
- idx = input_nodes.index(to_rename)
- onnx_model.graph.input[i].name = remap_inputs[idx]
- # change names of all nodes in the graph
- for i in range(len(onnx_model.graph.node)):
- # check node.input is to change to remap_inputs or remap_outputs
- for j in range(len(onnx_model.graph.node[i].input)):
- if onnx_model.graph.node[i].input[j] in input_nodes:
- to_rename = onnx_model.graph.node[i].input[j]
- idx = input_nodes.index(to_rename)
- onnx_model.graph.node[i].input[j] = remap_inputs[idx]
- if onnx_model.graph.node[i].input[j] in output_nodes:
- to_rename = onnx_model.graph.node[i].input[j]
- idx = output_nodes.index(to_rename)
- onnx_model.graph.node[i].input[j] = remap_outputs[idx]
- # check node.output is to change to remap_inputs or remap_outputs
- for j in range(len(onnx_model.graph.node[i].output)):
- if onnx_model.graph.node[i].output[j] in output_nodes:
- to_rename = onnx_model.graph.node[i].output[j]
- idx = output_nodes.index(to_rename)
- onnx_model.graph.node[i].output[j] = remap_outputs[idx]
- if onnx_model.graph.node[i].output[j] in input_nodes:
- to_rename = onnx_model.graph.node[i].output[j]
- idx = input_nodes.index(to_rename)
- onnx_model.graph.node[i].output[j] = remap_inputs[idx]
- # change names for graph output
- for i in range(len(onnx_model.graph.output)):
- if onnx_model.graph.output[i].name in output_nodes:
- to_rename = onnx_model.graph.output[i].name
- idx = output_nodes.index(to_rename)
- onnx_model.graph.output[i].name = remap_outputs[idx]
+ remapper = TidyIONames(onnx_model)
+ remapper.order()
+ remapper.update()
+
+
+def _check_ext():
+ dir_path = os.path.dirname(os.path.realpath(__file__))
+ ext_path = os.path.join(dir_path, 'one-import-onnx-ext')
+ if (os.path.isfile(ext_path)):
+ return ext_path
+ return None
def _convert(args):
@@ -200,6 +252,7 @@ def _convert(args):
# get file path to log
dir_path = os.path.dirname(os.path.realpath(__file__))
logfile_path = os.path.realpath(args.output_path) + '.log'
+ ext_path = _check_ext()
with open(logfile_path, 'wb') as f, tempfile.TemporaryDirectory() as tmpdir:
# save intermediate
@@ -207,6 +260,7 @@ def _convert(args):
tmpdir = os.path.dirname(logfile_path)
# convert onnx to tf saved model
onnx_model = onnx.load(getattr(args, 'input_path'))
+ _sanitize_io_names(onnx_model)
if _onnx_legalizer_enabled:
options = onnx_legalizer.LegalizeOptions
options.unroll_rnn = oneutils.is_valid_attr(args, 'unroll_rnn')
@@ -219,6 +273,30 @@ def _convert(args):
fixed_path = os.path.join(tmpdir,
os.path.splitext(basename)[0] + '~.onnx')
onnx.save(onnx_model, fixed_path)
+
+ if ext_path:
+ # save onnx_model to temporary alt file
+ basename = os.path.basename(getattr(args, 'input_path'))
+ alt_path = os.path.join(tmpdir, os.path.splitext(basename)[0] + '-alt.onnx')
+ onnx.save(onnx_model, alt_path)
+
+ # call extension with options
+ ext_cmd = [ext_path]
+ if oneutils.is_valid_attr(args, 'unroll_rnn'):
+ ext_cmd.append('--unroll_rnn')
+ if oneutils.is_valid_attr(args, 'unroll_lstm'):
+ ext_cmd.append('--unroll_lstm')
+ if oneutils.is_valid_attr(args, 'experimental_disable_batchmatmul_unfold'):
+ ext_cmd.append('--experimental_disable_batchmatmul_unfold')
+ if oneutils.is_valid_attr(args, 'save_intermediate'):
+ ext_cmd.append('--save_intermediate')
+ if oneutils.is_valid_attr(args, 'keep_io_order'):
+ ext_cmd.append('--keep_io_order')
+ ext_cmd.append(alt_path)
+ ext_cmd.append(getattr(args, 'output_path'))
+ oneutils.run(ext_cmd, logfile=f)
+ return
+
tf_savedmodel = onnx_tf.backend.prepare(onnx_model)
savedmodel_name = os.path.splitext(os.path.basename(
diff --git a/compiler/one-cmds/one-import-pytorch b/compiler/one-cmds/one-import-pytorch
index 3a61d22fc..f0dbf4146 100644
--- a/compiler/one-cmds/one-import-pytorch
+++ b/compiler/one-cmds/one-import-pytorch
@@ -20,7 +20,8 @@
# limitations under the License.
import argparse
-import importlib
+import importlib.machinery
+import importlib.util
import inspect
import os
import sys
diff --git a/compiler/one-cmds/one-infer b/compiler/one-cmds/one-infer
index 125db3e37..075e2bfa2 100644
--- a/compiler/one-cmds/one-infer
+++ b/compiler/one-cmds/one-infer
@@ -27,48 +27,13 @@ import ntpath
import os
import sys
+import onelib.backends as backends
import onelib.utils as oneutils
# TODO Find better way to suppress trackback on error
sys.tracebacklimit = 0
-def _search_backend_driver(driver):
- """
- [one hierarchy]
- one
- ├── backends
- ├── bin
- ├── doc
- ├── include
- ├── lib
- ├── optimization
- └── test
-
- The list where `one-infer` finds its backend driver
- - `bin` folder where `one-infer` exists
- - `backends/**/bin/` folder
-
- NOTE If there are drivers of the same name in different places,
- the closer to the top in the list, the higher the priority.
- """
- dir_path = os.path.dirname(os.path.realpath(__file__))
-
- # CASE 1: one/bin/{driver} is found
- driver_path = dir_path + '/' + driver
- if os.path.isfile(driver_path) and os.access(driver_path, os.X_OK):
- return driver_path
-
- # CASE 2: one/backends/**/bin/{driver} is found
- for driver_path in glob.glob(
- dir_path + '/../backends/**/bin/' + driver, recursive=True):
- if os.path.isfile(driver_path) and os.access(driver_path, os.X_OK):
- return driver_path
-
- # CASE 3: {driver} is found in nowhere
- return None
-
-
def _get_parser():
infer_usage = 'one-infer [-h] [-v] [-C CONFIG] [-d DRIVER] [--post-process POST_PROCESS] [--] [COMMANDS FOR BACKEND DRIVER]'
infer_detail = """
@@ -128,7 +93,7 @@ def _parse_arg(parser):
def _get_executable(args):
driver = oneutils.is_valid_attr(args, 'driver')
- executable = _search_backend_driver(driver)
+ executable = backends.search_driver(driver)
if executable:
return executable
else:
diff --git a/compiler/one-cmds/one-init b/compiler/one-cmds/one-init
index 299255c6f..f2ddc78fa 100644
--- a/compiler/one-cmds/one-init
+++ b/compiler/one-cmds/one-init
@@ -28,6 +28,7 @@ import os
import sys
import configparser
+import onelib.backends as backends
import onelib.utils as oneutils
# TODO Find better way to suppress trackback on error
@@ -85,45 +86,6 @@ class CommentableConfigParser(configparser.ConfigParser):
self[section][f'{comment_sign} {comment}'] = None
-def _get_backends_list():
- """
- [one hierarchy]
- one
- ├── backends
- ├── bin
- ├── doc
- ├── include
- ├── lib
- ├── optimization
- └── test
-
- The list where `one-init` finds its backends
- - `bin` folder where `one-init` exists
- - `backends` folder
-
- NOTE If there are backends of the same name in different places,
- the closer to the top in the list, the higher the priority.
- """
- dir_path = os.path.dirname(os.path.realpath(__file__))
- backend_set = set()
-
- # bin folder
- files = [f for f in glob.glob(dir_path + '/*-init')]
- # backends folder
- files += [f for f in glob.glob(dir_path + '/../backends/**/*-init', recursive=True)]
- # TODO find backends in `$PATH`
-
- backends_list = []
- for cand in files:
- base = ntpath.basename(cand)
- if (not base in backend_set) and os.path.isfile(cand) and os.access(
- cand, os.X_OK):
- backend_set.add(base)
- backends_list.append(cand)
-
- return backends_list
-
-
# TODO Add support for TF graphdef and bcq
def _get_parser(backends_list):
init_usage = (
@@ -348,7 +310,7 @@ def _get_model_type(parser, args):
def main():
# get backend list
- backends_list = _get_backends_list()
+ backends_list = backends.get_list('init')
# parse arguments
parser = _get_parser(backends_list)
diff --git a/compiler/one-cmds/one-prepare-venv b/compiler/one-cmds/one-prepare-venv
index baa88bede..a456a6b9c 100644
--- a/compiler/one-cmds/one-prepare-venv
+++ b/compiler/one-cmds/one-prepare-venv
@@ -26,16 +26,16 @@ VENV_PYTHON=${DRIVER_PATH}/venv/bin/python
if [ ! -f ${VENV_ACTIVATE} ]; then
# Create python virtual enviornment
- python3.8 -m venv "${DRIVER_PATH}/venv"
+ python3 -m venv "${DRIVER_PATH}/venv"
fi
# NOTE version
# - https://github.com/onnx/onnx/blob/master/docs/Versioning.md
# - https://github.com/onnx/onnx-tensorflow/blob/master/Versioning.md
-VER_TENSORFLOW=2.8.0
-VER_ONNX=1.11.0
-VER_ONNXRUNTIME=1.11.0
+VER_TENSORFLOW=2.12.1
+VER_ONNX=1.14.0
+VER_ONNXRUNTIME=1.15.0
VER_ONNX_TF=1.10.0
VER_PYDOT=1.4.2
@@ -64,10 +64,9 @@ else
${VENV_PYTHON} -m pip ${PIP_OPTIONS} install tensorflow-cpu==${VER_TENSORFLOW}
fi
${VENV_PYTHON} -m pip ${PIP_OPTIONS} install Pillow
-# TODO remove version fix, https://github.com/Samsung/ONE/issues/9240
-${VENV_PYTHON} -m pip ${PIP_OPTIONS} install tensorflow_probability==0.16.0
-# TODO remove version fix, https://github.com/Samsung/ONE/issues/10481
-${VENV_PYTHON} -m pip ${PIP_OPTIONS} install tensorflow_addons==0.16.1
+# Fix version to that of TF release date
+${VENV_PYTHON} -m pip ${PIP_OPTIONS} install tensorflow_probability==0.20.1
+${VENV_PYTHON} -m pip ${PIP_OPTIONS} install tensorflow_addons==0.20.0
# Install PyTorch and ONNX related
# NOTE set ONE_PREPVENV_TORCH_STABLE to override 'torch_stable.html' URL.
@@ -79,7 +78,7 @@ if [[ ! -z "$ONE_PREPVENV_TORCH_STABLE" ]]; then
fi
# TODO remove torch message
echo "Torch from '${ONE_PREPVENV_TORCH_STABLE}' -> '${TORCH_STABLE_URL}'"
-${VENV_PYTHON} -m pip ${PIP_OPTIONS} install torch==1.11.0+cpu -f ${TORCH_STABLE_URL}
+${VENV_PYTHON} -m pip ${PIP_OPTIONS} install torch==1.13.1+cpu -f ${TORCH_STABLE_URL}
${VENV_PYTHON} -m pip ${PIP_OPTIONS} install onnx==${VER_ONNX}
@@ -92,9 +91,8 @@ else
${VENV_PYTHON} -m pip ${PIP_OPTIONS} install onnx-tf==${VER_ONNX_TF}
fi
-# NOTE refer https://github.com/protocolbuffers/protobuf/issues/10051
-# TODO remove this when issue is resolved
-${VENV_PYTHON} -m pip ${PIP_OPTIONS} install --upgrade protobuf==3.20.1
+# Fix version to that of TF release date
+${VENV_PYTHON} -m pip ${PIP_OPTIONS} install --upgrade protobuf==4.23.3
# Install pydot for visq
${VENV_PYTHON} -m pip ${PIP_OPTIONS} install pydot==${VER_PYDOT}
diff --git a/compiler/one-cmds/one-prepare-venv.aarch64 b/compiler/one-cmds/one-prepare-venv.aarch64
new file mode 100644
index 000000000..c8850df82
--- /dev/null
+++ b/compiler/one-cmds/one-prepare-venv.aarch64
@@ -0,0 +1,139 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -e
+
+DRIVER_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+VENV_ACTIVATE=${DRIVER_PATH}/venv/bin/activate
+# NOTE please use venv's python instead of python after `source activation`.
+# This script is called by debian maintainer script, i.e. `postinst`.
+# Since debian maintainer script is called with sudo, `source activation` is ignored.
+VENV_PYTHON=${DRIVER_PATH}/venv/bin/python
+
+if [ ! -f ${VENV_ACTIVATE} ]; then
+ # Create python virtual enviornment
+ python3 -m venv "${DRIVER_PATH}/venv"
+fi
+
+# NOTE version
+# - https://github.com/onnx/onnx/blob/master/docs/Versioning.md
+# - https://github.com/onnx/onnx-tensorflow/blob/master/Versioning.md
+
+VER_TENSORFLOW=2.12.1
+VER_ONNX=1.14.0
+VER_ONNXRUNTIME=1.15.0
+VER_ONNX_TF=1.10.0
+VER_PYDOT=1.4.2
+
+# Install tensorflow
+
+PIP_TRUSTED_HOST="--trusted-host pypi.org "
+PIP_TRUSTED_HOST+="--trusted-host pypi.python.org "
+PIP_TRUSTED_HOST+="--trusted-host files.pythonhosted.org "
+PIP_TRUSTED_HOST+="--trusted-host download.pytorch.org "
+
+PIP_TIMEOUT="--default-timeout=1000 "
+
+PIP_OPTIONS="${PIP_TIMEOUT} ${PIP_TRUSTED_HOST}"
+
+# NOTE $ONE_PREPVENV_PIP_OPTION is to provide additional PIP options
+# such as ceritificate file behind firewall
+# ex) ONE_PREPVENV_PIP_OPTION="--cert SomePrivateCetificate.crt" ./one-prepare-venv
+if [[ ! -z "$ONE_PREPVENV_PIP_OPTION" ]]; then
+ PIP_OPTIONS+=" ${ONE_PREPVENV_PIP_OPTION} "
+fi
+
+${VENV_PYTHON} -m pip ${PIP_OPTIONS} install --upgrade pip setuptools
+if [ -n "${EXT_TENSORFLOW_WHL}" ]; then
+ ${VENV_PYTHON} -m pip ${PIP_OPTIONS} install ${EXT_TENSORFLOW_WHL}
+else
+ ${VENV_PYTHON} -m pip ${PIP_OPTIONS} install tensorflow==${VER_TENSORFLOW}
+fi
+${VENV_PYTHON} -m pip ${PIP_OPTIONS} install Pillow
+# Fix version to that of TF release date
+${VENV_PYTHON} -m pip ${PIP_OPTIONS} install tensorflow_probability==0.20.1
+#${VENV_PYTHON} -m pip ${PIP_OPTIONS} install tensorflow_addons==0.20.0
+
+# NOTE
+#
+# - Since tensorflow_addons 0.20.0 package distribution does not exist, it is
+# configured to build using the source code at the time of
+# one-prepare-env. This is not a perfect solution as it requires a build
+# environment at install time.
+#
+# - Later, it is necessary to change the pre-built package to be uploaded
+# and downloaded at the time of installation. (Or expect the appropriate
+# tensorflow_addons official package to be distributed.)
+
+# Make tempolary workspace for build
+BAZEL_BUILD_PATH=$(mktemp -d)
+pushd $BAZEL_BUILD_PATH
+source $VENV_ACTIVATE
+
+# Download tensorflow_addons source
+git clone https://github.com/tensorflow/addons.git
+cd addons
+git checkout -b r0.20 origin/r0.20
+
+# Install bazel
+wget https://github.com/bazelbuild/bazelisk/releases/download/v1.17.0/bazelisk-linux-arm64
+chmod 755 bazelisk-linux-arm64
+ln -s bazelisk-linux-arm64 bazel
+
+# This script links project with TensorFlow dependency
+python3 ./configure.py
+
+# Build
+./bazel build build_pip_pkg
+bazel-bin/build_pip_pkg artifacts
+
+# Install tensroflow_addons
+${VENV_PYTHON} -m pip ${PIP_OPTIONS} install artifacts/tensorflow_addons-*.whl
+
+# Remove tempolary workspace
+deactivate
+popd
+rm -rf $BAZEL_BUILD_PATH
+
+# Install PyTorch and ONNX related
+# NOTE set ONE_PREPVENV_TORCH_STABLE to override 'torch_stable.html' URL.
+# torch_stable.html points to download URL of torch wheel file(s)
+# but sometimes the server gets unstable, especially from in-house CI.
+TORCH_STABLE_URL="https://download.pytorch.org/whl/torch_stable.html"
+if [[ ! -z "$ONE_PREPVENV_TORCH_STABLE" ]]; then
+ TORCH_STABLE_URL="${ONE_PREPVENV_TORCH_STABLE}"
+fi
+# TODO remove torch message
+echo "Torch from '${ONE_PREPVENV_TORCH_STABLE}' -> '${TORCH_STABLE_URL}'"
+${VENV_PYTHON} -m pip ${PIP_OPTIONS} install torch==1.13.1 -f ${TORCH_STABLE_URL}
+
+${VENV_PYTHON} -m pip ${PIP_OPTIONS} install onnx==${VER_ONNX}
+
+${VENV_PYTHON} -m pip ${PIP_OPTIONS} install onnxruntime==${VER_ONNXRUNTIME}
+
+# Provide install of custom onnx-tf
+if [ -n "${EXT_ONNX_TF_WHL}" ]; then
+ ${VENV_PYTHON} -m pip ${PIP_OPTIONS} install ${EXT_ONNX_TF_WHL}
+else
+ ${VENV_PYTHON} -m pip ${PIP_OPTIONS} install onnx-tf==${VER_ONNX_TF}
+fi
+
+# Fix version to that of TF release date
+${VENV_PYTHON} -m pip ${PIP_OPTIONS} install --upgrade protobuf==4.23.3
+
+# Install pydot for visq
+${VENV_PYTHON} -m pip ${PIP_OPTIONS} install pydot==${VER_PYDOT}
diff --git a/compiler/one-cmds/one-prepare-venv.u2204 b/compiler/one-cmds/one-prepare-venv.u1804
index d4b0467c3..55c79c6e0 100644
--- a/compiler/one-cmds/one-prepare-venv.u2204
+++ b/compiler/one-cmds/one-prepare-venv.u1804
@@ -1,6 +1,6 @@
#!/bin/bash
-# Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -26,16 +26,16 @@ VENV_PYTHON=${DRIVER_PATH}/venv/bin/python
if [ ! -f ${VENV_ACTIVATE} ]; then
# Create python virtual enviornment
- python3 -m venv "${DRIVER_PATH}/venv"
+ python3.8 -m venv "${DRIVER_PATH}/venv"
fi
# NOTE version
# - https://github.com/onnx/onnx/blob/master/docs/Versioning.md
# - https://github.com/onnx/onnx-tensorflow/blob/master/Versioning.md
-VER_TENSORFLOW=2.10.1
-VER_ONNX=1.12.0
-VER_ONNXRUNTIME=1.12.1
+VER_TENSORFLOW=2.12.1
+VER_ONNX=1.14.0
+VER_ONNXRUNTIME=1.15.0
VER_ONNX_TF=1.10.0
VER_PYDOT=1.4.2
@@ -64,7 +64,9 @@ else
${VENV_PYTHON} -m pip ${PIP_OPTIONS} install tensorflow-cpu==${VER_TENSORFLOW}
fi
${VENV_PYTHON} -m pip ${PIP_OPTIONS} install Pillow
-${VENV_PYTHON} -m pip ${PIP_OPTIONS} install tensorflow_probability
+# Fix version to that of TF release date
+${VENV_PYTHON} -m pip ${PIP_OPTIONS} install tensorflow_probability==0.20.1
+${VENV_PYTHON} -m pip ${PIP_OPTIONS} install tensorflow_addons==0.20.0
# Install PyTorch and ONNX related
# NOTE set ONE_PREPVENV_TORCH_STABLE to override 'torch_stable.html' URL.
@@ -89,9 +91,8 @@ else
${VENV_PYTHON} -m pip ${PIP_OPTIONS} install onnx-tf==${VER_ONNX_TF}
fi
-# NOTE refer https://github.com/protocolbuffers/protobuf/issues/10051
-# TODO remove this when issue is resolved
-${VENV_PYTHON} -m pip ${PIP_OPTIONS} install --upgrade protobuf==3.19.6
+# Fix version to that of TF release date
+${VENV_PYTHON} -m pip ${PIP_OPTIONS} install --upgrade protobuf==4.23.3
# Install pydot for visq
${VENV_PYTHON} -m pip ${PIP_OPTIONS} install pydot==${VER_PYDOT}
diff --git a/compiler/one-cmds/one-profile b/compiler/one-cmds/one-profile
index 18a0456f4..bc5338dcc 100644
--- a/compiler/one-cmds/one-profile
+++ b/compiler/one-cmds/one-profile
@@ -26,6 +26,7 @@ import itertools
import ntpath
import os
import sys
+from types import SimpleNamespace
import onelib.utils as oneutils
@@ -92,15 +93,46 @@ def _get_parser(backends_list):
return parser
-def _verify_arg(parser, args):
+def _verify_arg(parser, args, cfg_args, backend_args, unknown_args):
"""verify given arguments"""
+ cmd_backend_exist = oneutils.is_valid_attr(args, 'backend')
+ cfg_backend_exist = oneutils.is_valid_attr(cfg_args, 'backend')
+ cfg_backends_exist = oneutils.is_valid_attr(cfg_args, 'backends')
+
# check if required arguments is given
missing = []
- if not oneutils.is_valid_attr(args, 'backend'):
+ if not cmd_backend_exist and not cfg_backend_exist and not cfg_backends_exist:
missing.append('-b/--backend')
if len(missing):
parser.error('the following arguments are required: ' + ' '.join(missing))
+ if not oneutils.is_valid_attr(args, 'config'):
+ if not backend_args and not unknown_args:
+ parser.error('commands for the backend is missing.')
+
+ if cfg_backend_exist and cfg_backends_exist:
+ parser.error(
+ '\'backend\' option and \'backends\' option cannot be used simultaneously.')
+
+ # Check if given backend from command line exists in the configuration file
+ if cmd_backend_exist and cfg_backend_exist:
+ if args.backend != cfg_args.backend:
+ parser.error('Not found the command of given backend')
+
+ if cfg_backend_exist and not oneutils.is_valid_attr(cfg_args, 'command'):
+ parser.error('\'command\' key is missing in the configuration file.')
+
+ if cfg_backends_exist:
+ cfg_backends = getattr(cfg_args, 'backends').split(',')
+ # check if commands of given backends exist
+ for b in cfg_backends:
+ if not oneutils.is_valid_attr(cfg_args, b):
+ parser.error('Not found the command for ' + b)
+ # Check if given backend from command line exists in the configuration file
+ if cmd_backend_exist:
+ if args.backend not in cfg_backends:
+ parser.error('Not found the command of given backend')
+
def _parse_arg(parser):
profile_args = []
@@ -139,25 +171,75 @@ def main():
args, backend_args, unknown_args = _parse_arg(parser)
# parse configuration file
- oneutils.parse_cfg(args.config, 'one-profile', args)
+ cfg_args = SimpleNamespace()
+ oneutils.parse_cfg(args.config, 'one-profile', cfg_args)
# verify arguments
- _verify_arg(parser, args)
-
- # make a command to run given backend driver
- profile_path = None
- backend_base = getattr(args, 'backend') + '-profile'
- for cand in backends_list:
- if ntpath.basename(cand) == backend_base:
- profile_path = cand
- if not profile_path:
- raise FileNotFoundError(backend_base + ' not found')
- profile_cmd = [profile_path] + backend_args + unknown_args
- if oneutils.is_valid_attr(args, 'command'):
- profile_cmd += getattr(args, 'command').split()
-
- # run backend driver
- oneutils.run(profile_cmd, err_prefix=backend_base)
+ _verify_arg(parser, args, cfg_args, backend_args, unknown_args)
+ '''
+ one-profile defines its behavior for below cases.
+
+ [1] one-profile -h
+ [2] one-profile -v
+ [3] one-profile -C ${cfg} (backend, command key in cfg)
+ [4] one-profile -C ${cfg} (backends key in cfg)
+ [5] one-profile -b ${backend} ${command}
+ [6] one-profile -b ${backend} -- ${command}
+ [7] one-profile -b ${backend} -C {cfg} (backend, command key in cfg)
+ [8] one-profile -b ${backend} -C {cfg} (backends key in cfg) (Only 'backend' is invoked,
+ even though cfg file has multiple backends)
+ [9] one-profile -b ${backend} -C ${cfg} -- ${command} (backend, command key in cfg)
+ [10] one-profile -b ${backend} -C ${cfg} -- ${command} (backends key in cfg) (Only 'backend' is invoked,
+ even though cfg file has multiple backends)
+
+ All other cases are not allowed or an undefined behavior.
+ '''
+ cmd_overwrite = False
+ if oneutils.is_valid_attr(args, 'config'):
+ # [9], [10]
+ if backend_args and not unknown_args:
+ given_backends = [args.backend]
+ cmd_overwrite = True
+ else:
+ # [7], [8]
+ if oneutils.is_valid_attr(args, 'backend'):
+ given_backends = [args.backend]
+ if oneutils.is_valid_attr(cfg_args, 'backend'):
+ assert (oneutils.is_valid_attr(cfg_args, 'command'))
+ setattr(cfg_args, args.backend, cfg_args.command)
+ else:
+ # [3]
+ if oneutils.is_valid_attr(cfg_args, 'backend'):
+ assert (oneutils.is_valid_attr(cfg_args, 'command'))
+ given_backends = [cfg_args.backend]
+ setattr(cfg_args, cfg_args.backend, cfg_args.command)
+ # [4]
+ if oneutils.is_valid_attr(cfg_args, 'backends'):
+ given_backends = cfg_args.backends.split(',')
+ # [5], [6]
+ else:
+ assert (backend_args or unknown_args)
+ given_backends = [args.backend]
+
+ for given_backend in given_backends:
+ # make a command to run given backend driver
+ profile_path = None
+ backend_base = given_backend + '-profile'
+ for cand in backends_list:
+ if ntpath.basename(cand) == backend_base:
+ profile_path = cand
+ if not profile_path:
+ raise FileNotFoundError(backend_base + ' not found')
+
+ profile_cmd = [profile_path]
+ if not cmd_overwrite and oneutils.is_valid_attr(cfg_args, given_backend):
+ profile_cmd += getattr(cfg_args, given_backend).split()
+ else:
+ profile_cmd += backend_args
+ profile_cmd += unknown_args
+
+ # run backend driver
+ oneutils.run(profile_cmd, err_prefix=backend_base)
if __name__ == '__main__':
diff --git a/compiler/one-cmds/one-quantize b/compiler/one-cmds/one-quantize
index 060892d3b..f686aad29 100644
--- a/compiler/one-cmds/one-quantize
+++ b/compiler/one-cmds/one-quantize
@@ -121,6 +121,18 @@ def _get_parser():
'maximum percentile (0.0~100.0, default=99.0). Algorithm parameter for calibration. This is valid when calibration algorithm is percentile.'
)
quantization_group.add_argument(
+ '--moving_avg_batch',
+ type=str,
+ help=
+ 'batch size of moving average (default=16). This is valid when calibration algorithm is moving_average.'
+ )
+ quantization_group.add_argument(
+ '--moving_avg_const',
+ type=str,
+ help=
+ 'hyperparameter (C) to compute moving average (default=0.1). Update equation: avg <- avg + C * (curr_batch_avg - avg). This is valid when calibration algorithm is moving_average.'
+ )
+ quantization_group.add_argument(
'--mode',
type=str,
help=
@@ -217,6 +229,38 @@ def _get_parser():
action='store_true',
help='convert quantized model to fake-quantized fp32 model.')
+ # arguments for requantize option
+ requantize_group = parser.add_argument_group('arguments for requantize option')
+
+ requantize_group.add_argument(
+ '--requantize',
+ action='store_true',
+ help='convert quantized model to another-typed quantized model (ex: int8 -> uin8).'
+ )
+
+ # arguments for ampq option
+ ampq_quant_group = parser.add_argument_group('arguments for ampq option')
+ # ampq
+ ampq_quant_group.add_argument(
+ '--ampq', action='store_true', help='quantize model using ampq solver.')
+
+ # ampq_qerror_ratio
+ ampq_quant_group.add_argument(
+ '--ampq_qerror_ratio', type=str, help='quantization error ratio ([0, 1])')
+
+ # ampq_algorithm
+ ampq_quant_group.add_argument(
+ '--ampq_algorithm', type=str, help='type of algorithm (bisection)')
+
+ ampq_quant_group.add_argument(
+ '--bisection_type', type=str, help="one of 'auto', 'i16_front', 'i16_back'")
+
+ # ampq_bisection_visq
+ ampq_quant_group.add_argument(
+ '--ampq_bisection_visq',
+ type=str,
+ help='.visq.json file path with quantization errors')
+
return parser
@@ -256,6 +300,29 @@ def _set_default_values(args):
setattr(args, 'min_percentile', '1.0')
if not oneutils.is_valid_attr(args, 'max_percentile'):
setattr(args, 'max_percentile', '99.0')
+ if not oneutils.is_valid_attr(args, 'moving_avg_batch'):
+ setattr(args, 'moving_avg_batch', '16')
+ if not oneutils.is_valid_attr(args, 'moving_avg_const'):
+ setattr(args, 'moving_avg_const', '0.1')
+ if not oneutils.is_valid_attr(args, 'ampq_algorithm'):
+ setattr(args, 'ampq_algorithm', 'bisection')
+ if not oneutils.is_valid_attr(args, 'bisection_type'):
+ setattr(args, 'bisection_type', 'auto')
+
+
+def _verify_arg_pre(parser, args):
+ """verify given arguments before default values are set"""
+ # check if required arguments is given
+ missing = []
+ if oneutils.is_valid_attr(args, 'requantize'):
+ if not oneutils.is_valid_attr(args,
+ 'input_model_dtype') and not oneutils.is_valid_attr(
+ args, 'input_dtype'):
+ missing.append('--input_model_dtype')
+ if not oneutils.is_valid_attr(args, 'quantized_dtype'):
+ missing.append('--quantized_dtype')
+ if len(missing):
+ parser.error('the following arguments are required: ' + ' '.join(missing))
def _verify_arg(parser, args):
@@ -294,6 +361,31 @@ def _verify_arg(parser, args):
parser.error(
'The same number of src_tensor_name and dst_tensor_name should be given.')
+ # Check calibration parameters
+ if oneutils.is_valid_attr(args, 'mode'):
+ if getattr(args, 'mode') == 'percentile':
+ # Check dtype
+ try:
+ min_percentile = float(getattr(args, 'min_percentile'))
+ except ValueError:
+ parser.error('min_percentile must be float')
+ try:
+ max_percentile = float(getattr(args, 'max_percentile'))
+ except ValueError:
+ parser.error('max_percentile must be float')
+ elif getattr(args, 'mode') == 'moving_average':
+ # Check dtype
+ try:
+ moving_avg_batch = int(getattr(args, 'moving_avg_batch'))
+ except ValueError:
+ parser.error('moving_avg_batch must be integer')
+ try:
+ moving_avg_const = float(getattr(args, 'moving_avg_const'))
+ except ValueError:
+ parser.error('moving_avg_const must be float')
+ else:
+ parser.error('Unsupported mode')
+
def _parse_arg(parser):
args = parser.parse_args()
@@ -305,6 +397,10 @@ def _parse_arg(parser):
def _quantize(args):
+ if oneutils.is_valid_attr(args, 'ampq'):
+ _ampq_solve(args)
+ return
+
if oneutils.is_valid_attr(args, 'force_quantparam'):
# write quantization parameters
_write_qparam(args)
@@ -320,6 +416,11 @@ def _quantize(args):
_fake_quantize(args)
return
+ if oneutils.is_valid_attr(args, 'requantize'):
+ # requantize model
+ _requantize(args)
+ return
+
# get file path to log
dir_path = os.path.dirname(os.path.realpath(__file__))
logfile_path = os.path.realpath(args.output_path) + '.log'
@@ -383,6 +484,8 @@ def _quantize(args):
.add_option_with_valid_args('--input_data_format', ['input_data_format']) \
.add_option_with_valid_args('--min_percentile', ['min_percentile']) \
.add_option_with_valid_args('--max_percentile', ['max_percentile']) \
+ .add_option_with_valid_args('--moving_avg_batch', ['moving_avg_batch']) \
+ .add_option_with_valid_args('--moving_avg_const', ['moving_avg_const']) \
.add_option_with_valid_args('--mode', ['mode']) \
.add_noarg_option_if_valid_arg('--generate_profile_data', 'generate_profile_data') \
.run()
@@ -551,6 +654,204 @@ def _fake_quantize(args):
.run()
+def _ampq_solve(args):
+ # get file path to log
+ dir_path = os.path.dirname(os.path.realpath(__file__))
+ logfile_path = os.path.realpath(args.output_path) + '.log'
+
+ with open(logfile_path, 'wb') as f, tempfile.TemporaryDirectory() as tmpdir:
+ if oneutils.is_valid_attr(args, 'save_intermediate'):
+ tmpdir = os.path.dirname(logfile_path)
+
+ # get driver path
+ record_minmax_path = os.path.join(dir_path, 'record-minmax')
+
+ tmp_minmax_recorded_path = os.path.join(
+ tmpdir,
+ os.path.splitext(os.path.basename(
+ args.input_path))[0]) + '.minmax_recorded.circle'
+
+ ## make a command to record min-max value of each tensor while running the representative dataset
+ record_minmax_cmd = Command(record_minmax_path, args, f)
+ record_minmax_cmd.add_noarg_option_if_valid_arg('--verbose', 'verbose') \
+ .add_option_with_valid_args('--input_model', ['input_path']) \
+ .add_option_with_values('--output_model', [tmp_minmax_recorded_path]) \
+ .add_option_with_valid_args('--input_data', ['input_data']) \
+ .add_option_with_valid_args('--input_data_format', ['input_data_format']) \
+ .add_option_with_valid_args('--min_percentile', ['min_percentile']) \
+ .add_option_with_valid_args('--max_percentile', ['max_percentile']) \
+ .add_option_with_valid_args('--moving_avg_batch', ['moving_avg_batch']) \
+ .add_option_with_valid_args('--moving_avg_const', ['moving_avg_const']) \
+ .add_option_with_valid_args('--mode', ['mode']) \
+ .add_noarg_option_if_valid_arg('--generate_profile_data', 'generate_profile_data') \
+ .run()
+
+ # process visq if needed
+ visq_file = None
+ if oneutils.is_valid_attr(args, 'ampq_bisection_visq'):
+ visq_file = getattr(args, 'ampq_bisection_visq')
+
+ if (oneutils.is_valid_attr(args, 'ampq_algorithm')
+ and oneutils.is_valid_attr(args, 'bisection_type')):
+ algorithm = getattr(args, 'ampq_algorithm')
+ bisection_type = getattr(args, 'bisection_type')
+ if algorithm == 'bisection' and bisection_type == 'auto' and visq_file is None:
+ # algorithm needs bisection but no file in input configuration
+
+ # to compute visq file we need q8 quantized model
+ q8_file = os.path.join(
+ tmpdir,
+ os.path.splitext(os.path.basename(
+ args.input_path))[0]) + '.visq.q8.circle'
+
+ # get drievr path
+ circle_quantizer_path = os.path.join(dir_path, 'circle-quantizer')
+ circle_quantizer_cmd = [circle_quantizer_path]
+ # verbose
+ if oneutils.is_valid_attr(args, 'verbose'):
+ circle_quantizer_cmd.append('--verbose')
+ circle_quantizer_cmd.append('--quantize_with_minmax')
+ circle_quantizer_cmd.append('float32')
+ circle_quantizer_cmd.append('uint8')
+ circle_quantizer_cmd.append('channel')
+
+ if oneutils.is_valid_attr(args, 'TF-style_maxpool'):
+ circle_quantizer_cmd.append('--TF-style_maxpool')
+
+ circle_quantizer_cmd.extend(['--input_type', 'uint8'])
+ circle_quantizer_cmd.extend(['--output_type', 'uint8'])
+
+ # input and output paths
+ circle_quantizer_cmd.append(tmp_minmax_recorded_path)
+ circle_quantizer_cmd.append(q8_file)
+
+ f.write((' '.join(circle_quantizer_cmd) + '\n').encode())
+
+ # run circle-quantizer
+ oneutils.run(
+ circle_quantizer_cmd, err_prefix="circle_quantizer", logfile=f)
+
+ # compute visq file
+ visq_path = os.path.join(dir_path, 'visq')
+
+ visq_file = os.path.join(
+ tmpdir,
+ os.path.splitext(os.path.basename(
+ args.input_path))[0]) + '.tae.visq.json'
+
+ visq_cmd = [visq_path]
+ visq_cmd.extend(['--fp32_circle', getattr(args, 'input_path')])
+ visq_cmd.extend(['--data', getattr(args, 'input_data')])
+ visq_cmd.extend(['--q_circle', q8_file])
+ visq_cmd.extend(['--tae_output', visq_file])
+ visq_cmd.extend(['--batch_size', "1"])
+ visq_cmd.append('--dump_dot_graph')
+ f.write((' '.join(visq_cmd) + '\n').encode())
+
+ # run visq
+ oneutils.run(visq_cmd, err_prefix="visq", logfile=f)
+
+ # get driver path
+ circle_mpqsolver_path = os.path.join(dir_path, 'circle-mpqsolver')
+
+ # solve for Mixed Precision Quantization configuration
+ ampq_quantize_cmd = [circle_mpqsolver_path]
+
+ # data
+ if oneutils.is_valid_attr(args, 'input_data'):
+ ampq_quantize_cmd.extend(['--data', getattr(args, 'input_data')])
+
+ # data format
+ if oneutils.is_valid_attr(args, 'input_data_format'):
+ ampq_quantize_cmd.extend(
+ ['--data_format', getattr(args, 'input_data_format')])
+
+ # qerror_ratio
+ if oneutils.is_valid_attr(args, 'ampq_qerror_ratio'):
+ ampq_quantize_cmd.extend(
+ ['--qerror_ratio', getattr(args, 'ampq_qerror_ratio')])
+
+ # algorithm
+ if oneutils.is_valid_attr(args, 'ampq_algorithm'):
+ algorithm = getattr(args, 'ampq_algorithm')
+ if algorithm == 'bisection':
+ if oneutils.is_valid_attr(args, 'bisection_type'):
+ bisection_type = getattr(args, 'bisection_type')
+ if bisection_type == 'auto':
+ ampq_quantize_cmd.extend(['--bisection', 'auto'])
+ elif bisection_type == 'i16_front':
+ ampq_quantize_cmd.extend(['--bisection', 'true'])
+ elif bisection_type == 'i16_back':
+ ampq_quantize_cmd.extend(['--bisection', 'false'])
+
+ # recorded model as input
+ ampq_quantize_cmd.extend(['--input_model', tmp_minmax_recorded_path])
+
+ # input_dtype
+ if oneutils.is_valid_attr(args, 'input_type'):
+ ampq_quantize_cmd.extend(['--input_dtype', getattr(args, 'input_type')])
+
+ # output dtype
+ if oneutils.is_valid_attr(args, 'output_type'):
+ ampq_quantize_cmd.extend(['--output_dtype', getattr(args, 'output_type')])
+
+ # output model
+ if oneutils.is_valid_attr(args, 'output_path'):
+ ampq_quantize_cmd.extend(['--output_model', getattr(args, 'output_path')])
+
+ # visq_file
+ if not (visq_file is None):
+ ampq_quantize_cmd.extend(['--visq_file', visq_file])
+
+ # save_intermediate
+ if oneutils.is_valid_attr(args, 'save_intermediate'):
+ intermediate_dir = os.path.dirname(logfile_path)
+ ampq_quantize_cmd.extend(['--save_intermediate', intermediate_dir])
+
+ if oneutils.is_valid_attr(args, 'verbose'):
+ ampq_quantize_cmd.append('--verbose')
+
+ f.write((' '.join(ampq_quantize_cmd) + '\n').encode())
+
+ # run ampq
+ oneutils.run(ampq_quantize_cmd, err_prefix="circle_mpqsolver", logfile=f)
+
+
+def _requantize(args):
+ # get file path to log
+ dir_path = os.path.dirname(os.path.realpath(__file__))
+ logfile_path = os.path.realpath(args.output_path) + '.log'
+
+ with open(logfile_path, 'wb') as f:
+ # get driver path
+ circle_quantizer_path = os.path.join(dir_path, 'circle-quantizer')
+
+ ## make a command to quantize and dequantize the weights of the model
+ circle_quantizer_cmd = [circle_quantizer_path]
+ # verbose
+ if oneutils.is_valid_attr(args, 'verbose'):
+ circle_quantizer_cmd.append('--verbose')
+ # requantize
+ circle_quantizer_cmd.append('--requantize')
+ # Use input_model_dtype if it exists. Use input_dtype otherwise.
+ if oneutils.is_valid_attr(args, 'input_model_dtype'):
+ circle_quantizer_cmd.append(getattr(args, 'input_model_dtype'))
+ elif oneutils.is_valid_attr(args, 'input_dtype'):
+ circle_quantizer_cmd.append(getattr(args, 'input_dtype'))
+ if oneutils.is_valid_attr(args, 'quantized_dtype'):
+ circle_quantizer_cmd.append(getattr(args, 'quantized_dtype'))
+ # input and output path
+ if oneutils.is_valid_attr(args, 'input_path'):
+ circle_quantizer_cmd.append(getattr(args, 'input_path'))
+ if oneutils.is_valid_attr(args, 'output_path'):
+ circle_quantizer_cmd.append(getattr(args, 'output_path'))
+
+ f.write((' '.join(circle_quantizer_cmd) + '\n').encode())
+
+ # run circle-quantizer
+ oneutils.run(circle_quantizer_cmd, err_prefix="circle_quantizer", logfile=f)
+
+
def main():
# parse arguments
parser = _get_parser()
@@ -559,6 +860,9 @@ def main():
# parse configuration file
oneutils.parse_cfg(args.config, 'one-quantize', args)
+ # verify arguments before default value setting
+ _verify_arg_pre(parser, args)
+
# set default values
_set_default_values(args)
diff --git a/compiler/one-cmds/onecc b/compiler/one-cmds/onecc
index 4cc774011..c7a76c535 100644
--- a/compiler/one-cmds/onecc
+++ b/compiler/one-cmds/onecc
@@ -24,6 +24,7 @@ import configparser
import os
import subprocess
import sys
+from types import SimpleNamespace
from onelib.CfgRunner import CfgRunner
from onelib.WorkflowRunner import WorkflowRunner
@@ -67,7 +68,7 @@ def _check_subtool_exists():
def _get_parser():
- onecc_usage = 'onecc [-h] [-v] [-C CONFIG] [-W WORKFLOW] [-O OPTIMIZATION] [COMMAND <args>]'
+ onecc_usage = 'onecc [-h] [-v] [-C CONFIG] [-b BACKEND] [-W WORKFLOW] [-O OPTIMIZATION] [COMMAND <args>]'
onecc_desc = 'Run ONE driver via several commands or configuration file'
parser = argparse.ArgumentParser(description=onecc_desc, usage=onecc_usage)
@@ -86,6 +87,9 @@ def _get_parser():
parser.add_argument(
'-W', '--workflow', type=str, metavar='WORKFLOW', help='run with workflow file')
+ parser.add_argument(
+ '-b', '--backend', type=str, help='generate code for given backend')
+
# just for help message
compile_group = parser.add_argument_group('compile to circle model')
for tool, desc in subtool_list['compile'].items():
@@ -111,6 +115,48 @@ def _parse_arg(parser):
return args
+def _verify_backend_args(parser, args):
+ """
+ verify one-profile, one-codegen arguments
+
+ This verification logic comes from each drivers' codes.
+ """
+ cfgparser = configparser.ConfigParser()
+ cfgparser.optionxform = str
+ cfgparser.read(args.config)
+
+ for driver in ['one-profile', 'one-codegen']:
+ if not driver in cfgparser:
+ continue
+
+ cfg_args = SimpleNamespace()
+ oneutils.parse_cfg(args.config, driver, cfg_args)
+ cmd_backend_exist = oneutils.is_valid_attr(args, 'backend')
+ cfg_backend_exist = oneutils.is_valid_attr(cfg_args, 'backend')
+ cfg_backends_exist = oneutils.is_valid_attr(cfg_args, 'backends')
+
+ if cfg_backend_exist and cfg_backends_exist:
+ parser.error(
+ "'backend' option and 'backends' option cannot be used simultaneously.")
+
+ # Check if given backend from command line exists in the configuration file
+ if cmd_backend_exist and cfg_backend_exist:
+ if args.backend != cfg_args.backend:
+ parser.error('Not found the command of given backend')
+
+ if cfg_backends_exist:
+ cfg_backends = getattr(cfg_args, 'backends').split(',')
+ # check if commands of given backends exist
+ for b in cfg_backends:
+ if not oneutils.is_valid_attr(cfg_args, b):
+ parser.error('Not found the command for ' + b)
+
+ # Check if given backend from command line exists in the configuration file
+ if cmd_backend_exist:
+ if args.backend not in cfg_backends:
+ parser.error('Not found the command of given backend')
+
+
def _verify_arg(parser, args):
"""verify given arguments"""
# check if required arguments is given
@@ -126,6 +172,13 @@ def _verify_arg(parser, args):
if not getattr(args, 'O') in opt_name_list:
parser.error('Invalid optimization option')
+ if oneutils.is_valid_attr(args, 'backend') and oneutils.is_valid_attr(
+ args, 'workflow'):
+ parser.error('\'backend\' option can be used only with \'config\' option')
+
+ if oneutils.is_valid_attr(args, 'backend'):
+ _verify_backend_args(parser, args)
+
def main():
# check if there is subtool argument
@@ -152,6 +205,8 @@ def main():
runner.detect_import_drivers(bin_dir)
if oneutils.is_valid_attr(args, 'O'):
runner.add_opt(getattr(args, 'O'))
+ if oneutils.is_valid_attr(args, 'backend'):
+ runner.set_backend(args.backend)
runner.run(bin_dir)
elif oneutils.is_valid_attr(args, 'workflow'):
runner = WorkflowRunner(args.workflow)
diff --git a/compiler/one-cmds/onelib/CfgRunner.py b/compiler/one-cmds/onelib/CfgRunner.py
index fe1c41a55..3a7b5fcbd 100644
--- a/compiler/one-cmds/onelib/CfgRunner.py
+++ b/compiler/one-cmds/onelib/CfgRunner.py
@@ -56,6 +56,8 @@ class CfgRunner:
# add_opt receives group name except first 'O'
self.add_opt(o[1:])
+ self.backend = None
+
def _verify_cfg(self, cfgparser):
if not cfgparser.has_section('onecc'):
if cfgparser.has_section('one-build'):
@@ -88,6 +90,9 @@ class CfgRunner:
)
self.opt = opt
+ def set_backend(self, backend: str):
+ self.backend = backend
+
def detect_import_drivers(self, dir):
self.import_drivers = list(oneutils.detect_one_import_drivers(dir).keys())
@@ -109,6 +114,8 @@ class CfgRunner:
options += ['-O', self.opt]
if verbose:
options.append('--verbose')
+ if (section == 'one-codegen' or section == 'one-profile') and self.backend:
+ options += ['-b', self.backend]
driver_path = os.path.join(working_dir, section)
cmd = [driver_path] + options
oneutils.run(cmd)
diff --git a/compiler/one-cmds/onelib/backends.py b/compiler/one-cmds/onelib/backends.py
new file mode 100644
index 000000000..9d7dad17e
--- /dev/null
+++ b/compiler/one-cmds/onelib/backends.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import glob
+import ntpath
+import os
+"""
+[one hierarchy]
+one
+├── backends
+├── bin
+├── doc
+├── include
+├── lib
+├── optimization
+└── test
+
+The list where `one-XXXX` finds its backends
+- `bin` folder where `one-XXXX` exists
+- `backends` folder
+
+NOTE If there are backends of the same name in different places,
+ the closer to the top in the list, the higher the priority.
+"""
+
+
+def get_list(cmdname):
+ dir_path = os.path.dirname(os.path.realpath(__file__))
+ backend_set = set()
+
+ # bin folder
+ files = [f for f in glob.glob(dir_path + '/../*-' + cmdname)]
+ # backends folder
+ files += [
+ f
+ for f in glob.glob(dir_path + '/../../backends/**/*-' + cmdname, recursive=True)
+ ]
+ # TODO find backends in `$PATH`
+
+ backends_list = []
+ for cand in files:
+ base = ntpath.basename(cand)
+ if (not base in backend_set) and os.path.isfile(cand) and os.access(
+ cand, os.X_OK):
+ backend_set.add(base)
+ backends_list.append(cand)
+
+ return backends_list
+
+
+def search_driver(driver):
+ dir_path = os.path.dirname(os.path.realpath(__file__))
+
+ # CASE 1: one/bin/{driver} is found
+ driver_path = dir_path + '/../' + driver
+ if os.path.isfile(driver_path) and os.access(driver_path, os.X_OK):
+ return driver_path
+
+ # CASE 2: one/backends/**/bin/{driver} is found
+ for driver_path in glob.glob(
+ dir_path + '/../../backends/**/bin/' + driver, recursive=True):
+ if os.path.isfile(driver_path) and os.access(driver_path, os.X_OK):
+ return driver_path
+
+ # CASE 3: {driver} is found in nowhere
+ return None
diff --git a/compiler/one-cmds/onelib/constant.py b/compiler/one-cmds/onelib/constant.py
index 0f338fced..90109ef40 100644
--- a/compiler/one-cmds/onelib/constant.py
+++ b/compiler/one-cmds/onelib/constant.py
@@ -40,6 +40,7 @@ class CONSTANT:
'fuse_activation_function',
'fuse_instnorm',
'fuse_prelu',
+ 'fuse_gelu',
'fuse_mean_with_mean',
'fuse_transpose_with_mean',
'transform_min_max_to_relu6',
@@ -109,6 +110,7 @@ class CONSTANT:
('fuse_activation_function', 'fuse Activation function to a preceding operator'),
('fuse_instnorm', 'fuse ops to InstanceNorm operator'),
('fuse_prelu', 'fuse ops to PReLU operator'),
+ ('fuse_gelu', 'fuse ops to GeLU operator'),
('replace_cw_mul_add_with_depthwise_conv',
'replace channel-wise Mul/Add with DepthwiseConv2D'),
('remove_fakequant', 'remove FakeQuant ops'),
@@ -143,7 +145,10 @@ class CONSTANT:
'convert certain condition Transpose to Reshape'),
('transform_min_max_to_relu6', 'transform Minimum-Maximum pattern to Relu6 op'),
('transform_min_relu_to_relu6', 'transform Minimum(6)-Relu pattern to Relu6 op'),
- ('unroll_unidirseqlstm', 'unroll UnidirectionalSequenceLSTM op'))
+ ('decompose_hardswish', 'decompose the HardSwish op to Add, Mul and Relu6 ops'),
+ ('unroll_unidirseqlstm', 'unroll UnidirectionalSequenceLSTM op'),
+ ('dynamic_batch_to_single_batch',
+ 'convert dynamic batch size (first dimension) of inputs to 1'))
CONSTANT = CONSTANT()
diff --git a/compiler/one-cmds/onelib/utils.py b/compiler/one-cmds/onelib/utils.py
index 3d37f9d49..f7a1a963a 100644
--- a/compiler/one-cmds/onelib/utils.py
+++ b/compiler/one-cmds/onelib/utils.py
@@ -17,7 +17,8 @@
import argparse
import configparser
import glob
-import importlib
+import importlib.machinery
+import importlib.util
import ntpath
import os
import subprocess
@@ -83,29 +84,6 @@ def is_valid_attr(args, attr):
return hasattr(args, attr) and getattr(args, attr)
-def parse_cfg_and_overwrite(config_path, section, args):
- """
- parse given section of configuration file and set the values of args.
- Even if the values parsed from the configuration file already exist in args,
- the values are overwritten.
- """
- if config_path == None:
- # DO NOTHING
- return
- config = configparser.ConfigParser()
- # make option names case sensitive
- config.optionxform = str
- parsed = config.read(config_path)
- if not parsed:
- raise FileNotFoundError('Not found given configuration file')
- if not config.has_section(section):
- raise AssertionError('configuration file doesn\'t have \'' + section +
- '\' section')
- for key in config[section]:
- setattr(args, key, config[section][key])
- # TODO support accumulated arguments
-
-
def parse_cfg(config_path: Union[str, None], section_to_parse: str, args):
"""
parse configuration file and store the information to args
diff --git a/compiler/one-cmds/requires.cmake b/compiler/one-cmds/requires.cmake
index c27920980..a25a7d70c 100644
--- a/compiler/one-cmds/requires.cmake
+++ b/compiler/one-cmds/requires.cmake
@@ -3,6 +3,7 @@ require("tflite2circle")
require("circle2circle")
require("circle-eval-diff")
require("circle-quantizer")
+require("circle-mpqsolver")
require("record-minmax")
require("vconone")
require("bcq-tools")
diff --git a/compiler/one-cmds/tests/one-codegen_neg_001.test b/compiler/one-cmds/tests/one-codegen_neg_001.test
index 27db02840..137a3f90d 100644
--- a/compiler/one-cmds/tests/one-codegen_neg_001.test
+++ b/compiler/one-cmds/tests/one-codegen_neg_001.test
@@ -21,7 +21,7 @@ filename="${filename_ext%.*}"
trap_err_onexit()
{
- if grep -q "error: the following arguments are required" "${filename}.log"; then
+ if grep -q "error: the following arguments are required: -b/--backend" "${filename}.log"; then
echo "${filename_ext} SUCCESS"
exit 0
fi
diff --git a/compiler/one-cmds/tests/one-codegen_neg_002.test b/compiler/one-cmds/tests/one-codegen_neg_002.test
new file mode 100644
index 000000000..28dfa920c
--- /dev/null
+++ b/compiler/one-cmds/tests/one-codegen_neg_002.test
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# one-codegen ${command} without backend option
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ if grep -q "error: the following arguments are required: -b/--backend" "${filename}.log"; then
+ echo "${filename_ext} SUCCESS"
+ exit 0
+ fi
+
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -f ${filename}.log
+
+# run test
+one-codegen -o test.tvn test.circle > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/one-codegen_neg_003.test b/compiler/one-cmds/tests/one-codegen_neg_003.test
new file mode 100644
index 000000000..0622b6a07
--- /dev/null
+++ b/compiler/one-cmds/tests/one-codegen_neg_003.test
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# one-codegen -- ${command} without backend option
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ if grep -q "error: the following arguments are required: -b/--backend" "${filename}.log"; then
+ echo "${filename_ext} SUCCESS"
+ exit 0
+ fi
+
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -f ${filename}.log
+
+# run test
+one-codegen -- -o test.tvn test.circle > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/one-codegen_neg_004.cfg b/compiler/one-cmds/tests/one-codegen_neg_004.cfg
new file mode 100644
index 000000000..b104fbb27
--- /dev/null
+++ b/compiler/one-cmds/tests/one-codegen_neg_004.cfg
@@ -0,0 +1,6 @@
+[onecc]
+one-codegen=True
+
+[one-codegen]
+backend=dummy
+# command=..
diff --git a/compiler/one-cmds/tests/one-codegen_neg_004.test b/compiler/one-cmds/tests/one-codegen_neg_004.test
new file mode 100644
index 000000000..c35549bdc
--- /dev/null
+++ b/compiler/one-cmds/tests/one-codegen_neg_004.test
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# command key is missing
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ if grep -q "error: 'command' key is missing in the configuration file" "${filename}.log"; then
+ echo "${filename_ext} SUCCESS"
+ exit 0
+ fi
+
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="one-codegen_neg_004.cfg"
+
+rm -f ${filename}.log
+
+# run test
+one-codegen -b dummy -C ${configfile} > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/one-codegen_neg_005.test b/compiler/one-cmds/tests/one-codegen_neg_005.test
new file mode 100644
index 000000000..4c52dcd89
--- /dev/null
+++ b/compiler/one-cmds/tests/one-codegen_neg_005.test
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# commands for the backend is missing
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ if grep -q "error: commands for the backend is missing" "${filename}.log"; then
+ echo "${filename_ext} SUCCESS"
+ exit 0
+ fi
+
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -f ${filename}.log
+
+# run test
+one-codegen -b dummy > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/one-import-onnx_ext_001.test b/compiler/one-cmds/tests/one-import-onnx_ext_001.test
new file mode 100644
index 000000000..be8dadcf1
--- /dev/null
+++ b/compiler/one-cmds/tests/one-import-onnx_ext_001.test
@@ -0,0 +1,53 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# test for one-import-onnx to invoke extension
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ rm -f ../bin/one-import-onnx-ext
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+inputfile="./onnx_conv2d_conv2d.onnx"
+outputfile="./onnx_conv2d_conv2d.onnx_ext_001.circle"
+logfile=${filename}.log
+
+rm -f ${outputfile}
+rm -f ${logfile}
+
+# copy dummy-compile to bin folder
+cp dummy-onnx-ext ../bin/one-import-onnx-ext
+
+# run test
+one-import-onnx \
+--input_path ${inputfile} \
+--output_path ${outputfile} > ${logfile} 2>&1
+
+if ! grep -q "one-import-onnx-ext dummy output!!!" "${logfile}"; then
+ trap_err_onexit
+fi
+
+rm -f ../bin/one-import-onnx-ext
+
+echo "${filename_ext} SUCCESS"
+exit 0
diff --git a/compiler/one-cmds/tests/one-import_neg_001.test b/compiler/one-cmds/tests/one-import_neg_001.test
index 82a3e338d..20a69641a 100644
--- a/compiler/one-cmds/tests/one-import_neg_001.test
+++ b/compiler/one-cmds/tests/one-import_neg_001.test
@@ -25,6 +25,11 @@ trap_err_onexit()
echo "${filename_ext} SUCCESS"
exit 0
fi
+ # TF 2.12.x: error report has changed
+ if grep -q "invalid start byte" "${filename}.log"; then
+ echo "${filename_ext} SUCCESS"
+ exit 0
+ fi
echo "${filename_ext} FAILED"
exit 255
diff --git a/compiler/one-cmds/tests/one-profile_neg_002.test b/compiler/one-cmds/tests/one-profile_neg_002.test
new file mode 100644
index 000000000..6964312a3
--- /dev/null
+++ b/compiler/one-cmds/tests/one-profile_neg_002.test
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# one-profile ${command} without backend option
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ if grep -q "error: the following arguments are required: -b/--backend" "${filename}.log"; then
+ echo "${filename_ext} SUCCESS"
+ exit 0
+ fi
+
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -f ${filename}.log
+
+# run test
+one-profile test.tvn > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/one-profile_neg_003.test b/compiler/one-cmds/tests/one-profile_neg_003.test
new file mode 100644
index 000000000..a00215452
--- /dev/null
+++ b/compiler/one-cmds/tests/one-profile_neg_003.test
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# one-profile -- ${command} without backend option
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ if grep -q "error: the following arguments are required: -b/--backend" "${filename}.log"; then
+ echo "${filename_ext} SUCCESS"
+ exit 0
+ fi
+
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -f ${filename}.log
+
+# run test
+one-profile -- test.tvn > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/one-profile_neg_004.cfg b/compiler/one-cmds/tests/one-profile_neg_004.cfg
new file mode 100644
index 000000000..93afcb4df
--- /dev/null
+++ b/compiler/one-cmds/tests/one-profile_neg_004.cfg
@@ -0,0 +1,6 @@
+[onecc]
+one-profile=True
+
+[one-profile]
+backend=dummy
+# command=..
diff --git a/compiler/one-cmds/tests/one-profile_neg_004.test b/compiler/one-cmds/tests/one-profile_neg_004.test
new file mode 100644
index 000000000..404ac1071
--- /dev/null
+++ b/compiler/one-cmds/tests/one-profile_neg_004.test
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# command key is missing
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ if grep -q "error: 'command' key is missing in the configuration file" "${filename}.log"; then
+ echo "${filename_ext} SUCCESS"
+ exit 0
+ fi
+
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="one-profile_neg_004.cfg"
+
+rm -f ${filename}.log
+
+# run test
+one-profile -b dummy -C ${configfile} > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/one-profile_neg_005.test b/compiler/one-cmds/tests/one-profile_neg_005.test
new file mode 100644
index 000000000..9a915497b
--- /dev/null
+++ b/compiler/one-cmds/tests/one-profile_neg_005.test
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# commands for the backend is missing
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ if grep -q "error: commands for the backend is missing" "${filename}.log"; then
+ echo "${filename_ext} SUCCESS"
+ exit 0
+ fi
+
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -f ${filename}.log
+
+# run test
+one-profile -b dummy > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/one-quantize_016.test b/compiler/one-cmds/tests/one-quantize_016.test
index 8bf0dd0fb..cfebc2f1e 100644
--- a/compiler/one-cmds/tests/one-quantize_016.test
+++ b/compiler/one-cmds/tests/one-quantize_016.test
@@ -54,8 +54,8 @@ if [[ ! -s "${outputfile}" ]]; then
trap_err_onexit
fi
-circledump ${outputfile} | grep serving_default_l.1:0$ > ${filename}.first.cdump
-circledump ${outputfile} | grep serving_default_r.1:0$ > ${filename}.second.cdump
+circledump ${outputfile} | grep "T(0:0)" > ${filename}.first.cdump
+circledump ${outputfile} | grep "T(0:1)" > ${filename}.second.cdump
# check dtype of the first input (uint8)
if ! grep -q "UINT8" "${filename}.first.cdump"; then
diff --git a/compiler/one-cmds/tests/one-quantize_017.test b/compiler/one-cmds/tests/one-quantize_017.test
new file mode 100644
index 000000000..f4d3ee834
--- /dev/null
+++ b/compiler/one-cmds/tests/one-quantize_017.test
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+inputfile="./mobilenet_edgetpu_224_1.0_int8.circle"
+outputfile="./mobilenet_edgetpu_224_1.0_int8.one-quantize_017.circle"
+
+rm -f ${filename}.log
+rm -f ${outputfile}
+
+# run test
+one-quantize \
+--requantize \
+--input_model_dtype int8 \
+--quantized_dtype uint8 \
+--input_path ${inputfile} \
+--output_path ${outputfile} > ${filename}.log 2>&1
+
+if [[ ! -s "${outputfile}" ]]; then
+ trap_err_onexit
+fi
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-quantize_018.test b/compiler/one-cmds/tests/one-quantize_018.test
new file mode 100644
index 000000000..dd609dda5
--- /dev/null
+++ b/compiler/one-cmds/tests/one-quantize_018.test
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# ampq test for bisection_type = 'i16_front' (front nodes will be quantized to int16)
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+inputfile="./inception_v3.circle"
+outputfile="./inception_v3.q_opt.one-quantize_018.circle"
+datafile="./inception_v3_test_data.h5"
+bisection_type="i16_front"
+
+rm -f ${filename}.log
+rm -f ${outputfile}
+
+# run test
+one-quantize \
+--input_data ${datafile} \
+--input_path ${inputfile} \
+--ampq \
+--ampq_qerror_ratio "0.5" \
+--ampq_algorithm "bisection" \
+--bisection_type ${bisection_type} \
+--output_path ${outputfile} > ${filename}.log 2>&1
+
+if [[ ! -s "${outputfile}" ]]; then
+ trap_err_onexit
+fi
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-quantize_019.test b/compiler/one-cmds/tests/one-quantize_019.test
new file mode 100644
index 000000000..3001fad4c
--- /dev/null
+++ b/compiler/one-cmds/tests/one-quantize_019.test
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# ampq test for bisection_type = 'i16_back' (output nodes will be quantized to int16)
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+inputfile="./inception_v3.circle"
+outputfile="./inception_v3.q_opt.one-quantize_019.circle"
+datafile="./inception_v3_test_data.h5"
+bisection_type="i16_back"
+
+rm -f ${filename}.log
+rm -f ${outputfile}
+
+# run test
+one-quantize \
+--input_data ${datafile} \
+--input_path ${inputfile} \
+--ampq \
+--ampq_qerror_ratio "0.5" \
+--ampq_algorithm "bisection" \
+--bisection_type ${bisection_type} \
+--output_path ${outputfile} > ${filename}.log 2>&1
+
+if [[ ! -s "${outputfile}" ]]; then
+ trap_err_onexit
+fi
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-quantize_020.test b/compiler/one-cmds/tests/one-quantize_020.test
new file mode 100644
index 000000000..5167295ee
--- /dev/null
+++ b/compiler/one-cmds/tests/one-quantize_020.test
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# ampq test with bisection_type set to auto
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+inputfile="./inception_v3.circle"
+outputfile="./inception_v3.q_opt.one-quantize_020.circle"
+datafile="./inception_v3_test_data.h5"
+bisection_type="auto"
+
+rm -f ${filename}.log
+rm -f ${outputfile}
+
+# run test
+one-quantize \
+--input_data ${datafile} \
+--input_path ${inputfile} \
+--ampq \
+--ampq_qerror_ratio "0.5" \
+--ampq_algorithm "bisection" \
+--bisection_type ${bisection_type} \
+--output_path ${outputfile} > ${filename}.log 2>&1
+
+if [[ ! -s "${outputfile}" ]]; then
+ trap_err_onexit
+fi
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-quantize_021.test b/compiler/one-cmds/tests/one-quantize_021.test
new file mode 100644
index 000000000..b6abc6682
--- /dev/null
+++ b/compiler/one-cmds/tests/one-quantize_021.test
@@ -0,0 +1,47 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Test moving average parameters (moving average per Image)
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+inputfile="./inception_v3.circle"
+outputfile="./inception_v3.one-quantize_021.circle"
+
+rm -f ${filename}.log
+rm -f ${outputfile}
+
+# run test
+one-quantize \
+--input_path ${inputfile} \
+--mode moving_average \
+--moving_avg_batch 1 \
+--moving_avg_const 0.01 \
+--output_path ${outputfile} > ${filename}.log 2>&1
+
+if [[ ! -s "${outputfile}" ]]; then
+ trap_err_onexit
+fi
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-quantize_neg_003.test b/compiler/one-cmds/tests/one-quantize_neg_003.test
index e8b96487b..af2db72c5 100644
--- a/compiler/one-cmds/tests/one-quantize_neg_003.test
+++ b/compiler/one-cmds/tests/one-quantize_neg_003.test
@@ -21,7 +21,7 @@ filename="${filename_ext%.*}"
trap_err_onexit()
{
- if grep -q "Input shape mismatch" "${filename}.log"; then
+ if grep -q "Buffer size does not match" "${filename}.log"; then
echo "${filename_ext} SUCCESS"
exit 0
fi
diff --git a/compiler/one-cmds/tests/one-quantize_neg_022.test b/compiler/one-cmds/tests/one-quantize_neg_022.test
new file mode 100644
index 000000000..519394175
--- /dev/null
+++ b/compiler/one-cmds/tests/one-quantize_neg_022.test
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Wrong number of input_type in one-quantize
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ if grep -q "following arguments are required: --input_model_dtype" "${filename}.log"; then
+ echo "${filename_ext} SUCCESS"
+ exit 0
+ fi
+
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+inputfile="./mobilenet_edgetpu_224_1.0_int8.circle"
+outputfile="./mobilenet_edgetpu_224_1.0_int8.one-quantize_neg_022.circle"
+
+rm -f ${filename}.log
+
+# run test with wrong input model dtype
+one-quantize \
+--requantize \
+--quantized_dtype uint8 \
+--input_path ${inputfile} \
+--output_path ${outputfile} > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/one-quantize_neg_023.test b/compiler/one-cmds/tests/one-quantize_neg_023.test
new file mode 100644
index 000000000..7ed97c18c
--- /dev/null
+++ b/compiler/one-cmds/tests/one-quantize_neg_023.test
@@ -0,0 +1,49 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Wrong type of calibration parameter
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ if grep -q "moving_avg_batch must be integer" "${filename}.log"; then
+ echo "${filename_ext} SUCCESS"
+ exit 0
+ fi
+
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+inputfile="./inception_v3.circle"
+outputfile="./inception_v3.one-quantize_neg_023.circle"
+
+rm -f ${filename}.log
+
+# run test with wrong parameter dtype
+# moving_avg_batch must be integer
+one-quantize \
+--input_path ${inputfile} \
+--mode moving_average \
+--moving_avg_batch 0.1 \
+--output_path ${outputfile} > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/onecc_045.test b/compiler/one-cmds/tests/onecc_045.test
index 74e21f630..2b5c0a21a 100644
--- a/compiler/one-cmds/tests/onecc_045.test
+++ b/compiler/one-cmds/tests/onecc_045.test
@@ -49,8 +49,8 @@ if [[ ! -s "${outputfile}" ]]; then
trap_err_onexit
fi
-circledump ${outputfile} | grep serving_default_l.1:0$ > ${filename}.first.cdump
-circledump ${outputfile} | grep serving_default_r.1:0$ > ${filename}.second.cdump
+circledump ${outputfile} | grep "T(0:0)" > ${filename}.first.cdump
+circledump ${outputfile} | grep "T(0:1)" > ${filename}.second.cdump
# check dtype of the first input (uint8)
if ! grep -q "UINT8" "${filename}.first.cdump"; then
diff --git a/compiler/one-cmds/tests/onecc_046.cfg b/compiler/one-cmds/tests/onecc_046.cfg
new file mode 100644
index 000000000..28927355b
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_046.cfg
@@ -0,0 +1,7 @@
+[onecc]
+one-codegen=True
+
+[one-codegen]
+backends=dummy,dummyV2
+dummy=-o onecc_046.tvn inception_v3.onecc_046.circle
+dummyV2=-O onecc_046.2.tvn inception_v3.onecc_046.2.circle
diff --git a/compiler/one-cmds/tests/onecc_046.test b/compiler/one-cmds/tests/onecc_046.test
new file mode 100644
index 000000000..a11b181d5
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_046.test
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# 'backends' key in configuration file
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ rm -rf ../bin/dummy-compile
+ rm -rf ../bin/dummyV2-compile
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="onecc_046.cfg"
+outputfile="onecc_046.tvn"
+outputfile2="onecc_046.2.tvn"
+
+rm -f ${filename}.log
+rm -rf ${outputfile}
+rm -rf ${outputfile2}
+
+# copy dummy tools to bin folder
+cp dummy-compile ../bin/dummy-compile
+cp dummyV2-compile ../bin/dummyV2-compile
+
+# run test
+onecc -C ${configfile} > ${filename}.log 2>&1
+
+if [[ ! -s "${outputfile}" ]]; then
+ trap_err_onexit
+fi
+
+if [[ ! -s "${outputfile2}" ]]; then
+ trap_err_onexit
+fi
+
+rm -rf ../bin/dummy-compile
+rm -rf ../bin/dummyV2-compile
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/onecc_047.cfg b/compiler/one-cmds/tests/onecc_047.cfg
new file mode 100644
index 000000000..df2eef5f8
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_047.cfg
@@ -0,0 +1,7 @@
+[onecc]
+one-codegen=True
+
+[one-codegen]
+backends=dummy,dummyV2
+dummy=-o onecc_047.tvn inception_v3.onecc_047.circle
+dummyV2=-O onecc_047.2.tvn inception_v3.onecc_047.2.circle
diff --git a/compiler/one-cmds/tests/onecc_047.test b/compiler/one-cmds/tests/onecc_047.test
new file mode 100644
index 000000000..345042091
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_047.test
@@ -0,0 +1,59 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# 'backends' key in configuration file but run codegen for only one backend
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ rm -rf ../bin/dummy-compile
+ rm -rf ../bin/dummyV2-compile
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="onecc_047.cfg"
+outputfile="onecc_047.tvn"
+outputfile2="onecc_047.2.tvn"
+
+rm -f ${filename}.log
+rm -rf ${outputfile}
+rm -rf ${outputfile2}
+
+# copy dummy tools to bin folder
+cp dummy-compile ../bin/dummy-compile
+cp dummyV2-compile ../bin/dummyV2-compile
+
+# run test
+onecc -C ${configfile} -b dummyV2 > ${filename}.log 2>&1
+
+# shouldn't be generated
+if [[ -s "${outputfile}" ]]; then
+ trap_err_onexit
+fi
+
+if [[ ! -s "${outputfile2}" ]]; then
+ trap_err_onexit
+fi
+
+rm -rf ../bin/dummy-compile
+rm -rf ../bin/dummyV2-compile
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/onecc_048.cfg b/compiler/one-cmds/tests/onecc_048.cfg
new file mode 100644
index 000000000..c4c0acc40
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_048.cfg
@@ -0,0 +1,6 @@
+[onecc]
+one-codegen=True
+
+[one-codegen]
+backend=dummyV2
+command=-O onecc_048.tvn inception_v3.onecc_048.circle
diff --git a/compiler/one-cmds/tests/onecc_048.test b/compiler/one-cmds/tests/onecc_048.test
new file mode 100644
index 000000000..d4eff54cf
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_048.test
@@ -0,0 +1,49 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# 'backend' option from command line with 'backend' key in configuration file
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ rm -rf ../bin/dummyV2-compile
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="onecc_048.cfg"
+outputfile="onecc_048.tvn"
+
+rm -f ${filename}.log
+rm -rf ${outputfile}
+
+# copy dummy tools to bin folder
+cp dummyV2-compile ../bin/dummyV2-compile
+
+# run test
+onecc -C ${configfile} -b dummyV2 > ${filename}.log 2>&1
+
+if [[ ! -s "${outputfile}" ]]; then
+ trap_err_onexit
+fi
+
+rm -rf ../bin/dummyV2-compile
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/onecc_049.cfg b/compiler/one-cmds/tests/onecc_049.cfg
new file mode 100644
index 000000000..021d9a45e
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_049.cfg
@@ -0,0 +1,7 @@
+[onecc]
+one-profile=True
+
+[one-profile]
+backends=dummy,dummyV2
+dummy=dummy.bin
+dummyV2=dummyV2.bin
diff --git a/compiler/one-cmds/tests/onecc_049.test b/compiler/one-cmds/tests/onecc_049.test
new file mode 100644
index 000000000..45fd8a74b
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_049.test
@@ -0,0 +1,54 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# 'backends' key in one-profile section
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ rm -rf ../bin/dummy-profile
+ rm -rf ../bin/dummyV2-profile
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="onecc_049.cfg"
+
+rm -f ${filename}.log
+
+# copy dummy tools to bin folder
+cp dummy-profile ../bin/dummy-profile
+cp dummyV2-profile ../bin/dummyV2-profile
+
+# run test
+onecc -C ${configfile} > ${filename}.log 2>&1
+
+if ! grep -q "dummy-profile dummy output!!!" "${filename}.log"; then
+ trap_err_onexit
+fi
+
+if ! grep -q "dummyV2-profile dummy output!!!" "${filename}.log"; then
+ trap_err_onexit
+fi
+
+rm -rf ../bin/dummy-profile
+rm -rf ../bin/dummyV2-profile
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/onecc_050.cfg b/compiler/one-cmds/tests/onecc_050.cfg
new file mode 100644
index 000000000..021d9a45e
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_050.cfg
@@ -0,0 +1,7 @@
+[onecc]
+one-profile=True
+
+[one-profile]
+backends=dummy,dummyV2
+dummy=dummy.bin
+dummyV2=dummyV2.bin
diff --git a/compiler/one-cmds/tests/onecc_050.test b/compiler/one-cmds/tests/onecc_050.test
new file mode 100644
index 000000000..8ebfd1e81
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_050.test
@@ -0,0 +1,54 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# 'backends' key in configuration file but run one-profile for only one backend
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ rm -rf ../bin/dummy-profile
+ rm -rf ../bin/dummyV2-profile
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="onecc_050.cfg"
+
+rm -f ${filename}.log
+
+# copy dummy tools to bin folder
+cp dummy-profile ../bin/dummy-profile
+cp dummyV2-profile ../bin/dummyV2-profile
+
+# run test
+onecc -C ${configfile} -b dummyV2 > ${filename}.log 2>&1
+
+if grep -q "dummy-profile dummy output!!!" "${filename}.log"; then
+ trap_err_onexit
+fi
+
+if ! grep -q "dummyV2-profile dummy output!!!" "${filename}.log"; then
+ trap_err_onexit
+fi
+
+rm -rf ../bin/dummy-profile
+rm -rf ../bin/dummyV2-profile
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/onecc_051.cfg b/compiler/one-cmds/tests/onecc_051.cfg
new file mode 100644
index 000000000..ecf983f71
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_051.cfg
@@ -0,0 +1,6 @@
+[onecc]
+one-profile=True
+
+[one-profile]
+backend=dummyV2
+command=dummyV2.bin
diff --git a/compiler/one-cmds/tests/onecc_051.test b/compiler/one-cmds/tests/onecc_051.test
new file mode 100644
index 000000000..97967096c
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_051.test
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# 'backend' option from command line with 'backend' key in configuration file
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ rm -rf ../bin/dummy-profile
+ rm -rf ../bin/dummyV2-profile
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="onecc_051.cfg"
+
+rm -f ${filename}.log
+
+# copy dummy tools to bin folder
+cp dummyV2-profile ../bin/dummyV2-profile
+
+# run test
+onecc -C ${configfile} -b dummyV2 > ${filename}.log 2>&1
+
+if ! grep -q "dummyV2-profile dummy output!!!" "${filename}.log"; then
+ trap_err_onexit
+fi
+
+rm -rf ../bin/dummyV2-profile
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/onecc_052.cfg b/compiler/one-cmds/tests/onecc_052.cfg
new file mode 100644
index 000000000..e884ea9a8
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_052.cfg
@@ -0,0 +1,13 @@
+[onecc]
+one-codegen=True
+one-profile=True
+
+[one-codegen]
+backends=dummy,dummyV2
+dummy=-o onecc_052.tvn inception_v3.onecc_052.circle
+dummyV2=-O onecc_052.2.tvn inception_v3.onecc_052.2.circle
+
+[one-profile]
+backends=dummy,dummyV2
+dummy=dummy.bin
+dummyV2=dummyV2.bin
diff --git a/compiler/one-cmds/tests/onecc_052.test b/compiler/one-cmds/tests/onecc_052.test
new file mode 100644
index 000000000..39bc6ed68
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_052.test
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# 'backends' key with one-profile and one-codgen section
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ rm -rf ../bin/dummy-profile
+ rm -rf ../bin/dummyV2-profile
+ rm -rf ../bin/dummy-compile
+ rm -rf ../bin/dummyV2-compile
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="onecc_052.cfg"
+outputfile="onecc_052.tvn"
+outputfile2="onecc_052.2.tvn"
+
+rm -f ${filename}.log
+rm -rf ${outputfile}
+rm -rf ${outputfile2}
+
+# copy dummy tools to bin folder
+cp dummy-profile ../bin/dummy-profile
+cp dummyV2-profile ../bin/dummyV2-profile
+cp dummy-compile ../bin/dummy-compile
+cp dummyV2-compile ../bin/dummyV2-compile
+
+# run test
+onecc -C ${configfile} > ${filename}.log 2>&1
+
+if ! grep -q "dummy-profile dummy output!!!" "${filename}.log"; then
+ trap_err_onexit
+fi
+
+if ! grep -q "dummyV2-profile dummy output!!!" "${filename}.log"; then
+ trap_err_onexit
+fi
+
+if [[ ! -s "${outputfile}" ]]; then
+ echo "ERROR: Not found ${outputfile}" >> ${filename}.log
+ trap_err_onexit
+fi
+
+if [[ ! -s "${outputfile2}" ]]; then
+echo "ERROR: Not found ${outputfile2}" >> ${filename}.log
+ trap_err_onexit
+fi
+
+rm -rf ../bin/dummy-profile
+rm -rf ../bin/dummyV2-profile
+rm -rf ../bin/dummy-compile
+rm -rf ../bin/dummyV2-compile
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/onecc_053.cfg b/compiler/one-cmds/tests/onecc_053.cfg
new file mode 100644
index 000000000..8cbe799b1
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_053.cfg
@@ -0,0 +1,13 @@
+[onecc]
+one-codegen=True
+one-profile=True
+
+[one-codegen]
+backends=dummy,dummyV2
+dummy=-o onecc_053.tvn inception_v3.onecc_053.circle
+dummyV2=-O onecc_053.2.tvn inception_v3.onecc_053.2.circle
+
+[one-profile]
+backends=dummy,dummyV2
+dummy=dummy.bin
+dummyV2=dummyV2.bin
diff --git a/compiler/one-cmds/tests/onecc_053.test b/compiler/one-cmds/tests/onecc_053.test
new file mode 100644
index 000000000..20f0209ad
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_053.test
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# 'backend' option with one-profile and one-codgen section
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ rm -rf ../bin/dummy-profile
+ rm -rf ../bin/dummyV2-profile
+ rm -rf ../bin/dummy-compile
+ rm -rf ../bin/dummyV2-compile
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="onecc_053.cfg"
+outputfile="onecc_053.tvn"
+outputfile2="onecc_053.2.tvn"
+
+rm -f ${filename}.log
+rm -rf ${outputfile}
+rm -rf ${outputfile2}
+
+# copy dummy tools to bin folder
+cp dummy-profile ../bin/dummy-profile
+cp dummyV2-profile ../bin/dummyV2-profile
+cp dummy-compile ../bin/dummy-compile
+cp dummyV2-compile ../bin/dummyV2-compile
+
+# run test
+onecc -C ${configfile} -b dummyV2 > ${filename}.log 2>&1
+
+if grep -q "dummy-profile dummy output!!!" "${filename}.log"; then
+ trap_err_onexit
+fi
+
+if ! grep -q "dummyV2-profile dummy output!!!" "${filename}.log"; then
+ trap_err_onexit
+fi
+
+if [[ -s "${outputfile}" ]]; then
+ echo "ERROR: Found ${outputfile}" >> ${filename}.log
+ trap_err_onexit
+fi
+
+if [[ ! -s "${outputfile2}" ]]; then
+echo "ERROR: Not found ${outputfile2}" >> ${filename}.log
+ trap_err_onexit
+fi
+
+rm -rf ../bin/dummy-profile
+rm -rf ../bin/dummyV2-profile
+rm -rf ../bin/dummy-compile
+rm -rf ../bin/dummyV2-compile
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/onecc_054.cfg b/compiler/one-cmds/tests/onecc_054.cfg
new file mode 100644
index 000000000..63ad06ccf
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_054.cfg
@@ -0,0 +1,7 @@
+[onecc]
+one-codegen=True
+
+[one-codegen]
+backends=dummy,dummyV2
+dummy=-o onecc_054.tvn inception_v3.onecc_054.circle
+dummyV2=-O onecc_054.2.tvn inception_v3.onecc_054.2.circle
diff --git a/compiler/one-cmds/tests/onecc_054.test b/compiler/one-cmds/tests/onecc_054.test
new file mode 100644
index 000000000..14853a8a3
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_054.test
@@ -0,0 +1,65 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# overwrite one-codegen command with `backends` key
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ rm -rf ../bin/dummy-compile
+ rm -rf ../bin/dummyV2-compile
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="onecc_054.cfg"
+outputfile0="onecc_054_overwrite.tvn"
+outputfile1="onecc_054.tvn"
+outputfile2="onecc_054.2.tvn"
+
+rm -f ${filename}.log
+rm -rf ${outputfile0}
+rm -rf ${outputfile1}
+rm -rf ${outputfile2}
+
+# copy dummy tools to bin folder
+cp dummy-compile ../bin/dummy-compile
+cp dummyV2-compile ../bin/dummyV2-compile
+
+# run test
+onecc codegen -C ${configfile} -b dummyV2 -- \
+ -O onecc_054_overwrite.tvn onecc.circle > ${filename}.log 2>&1
+
+if [[ ! -s "${outputfile0}" ]]; then
+ trap_err_onexit
+fi
+
+# shouldn't be generated
+if [[ -s "${outputfile1}" ]]; then
+ trap_err_onexit
+fi
+if [[ -s "${outputfile2}" ]]; then
+ trap_err_onexit
+fi
+
+rm -rf ../bin/dummy-compile
+rm -rf ../bin/dummyV2-compile
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/onecc_055.cfg b/compiler/one-cmds/tests/onecc_055.cfg
new file mode 100644
index 000000000..c4c0acc40
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_055.cfg
@@ -0,0 +1,6 @@
+[onecc]
+one-codegen=True
+
+[one-codegen]
+backend=dummyV2
+command=-O onecc_048.tvn inception_v3.onecc_048.circle
diff --git a/compiler/one-cmds/tests/onecc_055.test b/compiler/one-cmds/tests/onecc_055.test
new file mode 100644
index 000000000..c13aa4b08
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_055.test
@@ -0,0 +1,57 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# overwrite one-codegen command with `backend` and `command` key
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ rm -rf ../bin/dummyV2-compile
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="onecc_055.cfg"
+outputfile0="onecc_055.tvn"
+outputfile1="onecc_055_overwrite.tvn"
+
+rm -f ${filename}.log
+rm -rf ${outputfile0}
+rm -rf ${outputfile1}
+
+# copy dummy tools to bin folder
+cp dummyV2-compile ../bin/dummyV2-compile
+
+# run test
+onecc codegen -C ${configfile} -b dummyV2 -- \
+ -O onecc_055_overwrite.tvn onecc.circle > ${filename}.log 2>&1
+
+if [[ ! -s "${outputfile1}" ]]; then
+ trap_err_onexit
+fi
+
+# shouldn't be generated
+if [[ -s "${outputfile0}" ]]; then
+ trap_err_onexit
+fi
+
+rm -rf ../bin/dummyV2-compile
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/onecc_056.cfg b/compiler/one-cmds/tests/onecc_056.cfg
new file mode 100644
index 000000000..1d30fd78b
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_056.cfg
@@ -0,0 +1,6 @@
+[onecc]
+one-profile=True
+
+[one-profile]
+backend=dummyV3
+command=onecc_056
diff --git a/compiler/one-cmds/tests/onecc_056.test b/compiler/one-cmds/tests/onecc_056.test
new file mode 100644
index 000000000..159cafbb4
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_056.test
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# overwrite one-profile command with 'backend' key
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ rm -rf ../bin/dummyV3-profile
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="onecc_056.cfg"
+
+rm -f ${filename}.log
+
+# copy dummy tools to bin folder
+cp dummyV3-profile ../bin/dummyV3-profile
+
+# run test
+onecc profile -C ${configfile} -b dummyV3 -- \
+ onecc_056_overwrite > ${filename}.log 2>&1
+
+if ! grep -q "dummyV3-profile with onecc_056_overwrite" "${filename}.log"; then
+ trap_err_onexit
+fi
+
+rm -rf ../bin/dummyV3-profile
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/onecc_057.cfg b/compiler/one-cmds/tests/onecc_057.cfg
new file mode 100644
index 000000000..dbe4f531a
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_057.cfg
@@ -0,0 +1,7 @@
+[onecc]
+one-profile=True
+
+[one-profile]
+backends=dummyV2,dummyV3
+dummyV2=dummyV2.bin
+dummyV3=onecc_057
diff --git a/compiler/one-cmds/tests/onecc_057.test b/compiler/one-cmds/tests/onecc_057.test
new file mode 100644
index 000000000..f0076093b
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_057.test
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# overwrite one-profile command with `backends` key
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ rm -rf ../bin/dummyV2-profile
+ rm -rf ../bin/dummyV3-profile
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="onecc_057.cfg"
+
+rm -f ${filename}.log
+
+# copy dummy tools to bin folder
+cp dummyV2-profile ../bin/dummyV2-profile
+cp dummyV3-profile ../bin/dummyV3-profile
+
+# run test
+onecc profile -C ${configfile} -b dummyV3 -- \
+ onecc_057_overwrite > ${filename}.log 2>&1
+
+if ! grep -q "dummyV3-profile with onecc_057_overwrite" "${filename}.log"; then
+ trap_err_onexit
+fi
+
+rm -rf ../bin/dummyV2-profile
+rm -rf ../bin/dummyV3-profile
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/onecc_058.cfg b/compiler/one-cmds/tests/onecc_058.cfg
new file mode 100644
index 000000000..1d0b6d1f2
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_058.cfg
@@ -0,0 +1,9 @@
+[onecc]
+one-quantize=True
+
+[one-quantize]
+requantize=True
+input_path=mobilenet_edgetpu_224_1.0_int8.circle
+output_path=mobilenet_edgetpu_224_1.0_int8.onecc_058.circle
+input_model_dtype=int8
+quantized_dtype=uint8
diff --git a/compiler/one-cmds/tests/onecc_058.test b/compiler/one-cmds/tests/onecc_058.test
new file mode 100644
index 000000000..6f60eed8a
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_058.test
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="onecc_058.cfg"
+outputfile="mobilenet_edgetpu_224_1.0_int8.onecc_058.circle"
+
+rm -f ${filename}.log
+rm -rf ${outputfile}
+
+# run test
+onecc -C ${configfile} > ${filename}.log 2>&1
+
+if [[ ! -s "${outputfile}" ]]; then
+ trap_err_onexit
+fi
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/onecc_neg_027.cfg b/compiler/one-cmds/tests/onecc_neg_027.cfg
new file mode 100644
index 000000000..27f3f67cf
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_neg_027.cfg
@@ -0,0 +1,7 @@
+[onecc]
+one-codegen=True
+
+[one-codegen]
+backends=dummy,dummyV2
+dummy=-o sample.tvn inception_v3.onecc_neg_027.circle
+# dummyV2=-O sample2.tvn inception_v3.onecc_neg_027.circle
diff --git a/compiler/one-cmds/tests/onecc_neg_027.test b/compiler/one-cmds/tests/onecc_neg_027.test
new file mode 100644
index 000000000..f96825623
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_neg_027.test
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# not found the command for given backend
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ if grep -q "Not found the command for dummyV2" "${filename}.log"; then
+ echo "${filename_ext} SUCCESS"
+ exit 0
+ fi
+
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="onecc_neg_027.cfg"
+
+rm -f ${filename}.log
+
+# run test
+onecc -C ${configfile} > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/onecc_neg_028.cfg b/compiler/one-cmds/tests/onecc_neg_028.cfg
new file mode 100644
index 000000000..ca19c53ba
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_neg_028.cfg
@@ -0,0 +1,9 @@
+[onecc]
+one-codegen=True
+
+[one-codegen]
+backend=dummy3
+command=-o sample.tvn inception_v3.onecc_neg_028.circle
+backends=dummy,dummy2
+dummy=-o sample.tvn inception_v3.onecc_neg_028.circle
+dummyV2=-O sample2.tvn inception_v3.onecc_neg_028.circle
diff --git a/compiler/one-cmds/tests/onecc_neg_028.test b/compiler/one-cmds/tests/onecc_neg_028.test
new file mode 100644
index 000000000..beba24ab6
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_neg_028.test
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# use 'backend' and 'backends' option simultaneously
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ if grep -q "option cannot be used simultaneously" "${filename}.log"; then
+ echo "${filename_ext} SUCCESS"
+ exit 0
+ fi
+
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="onecc_neg_028.cfg"
+
+rm -f ${filename}.log
+
+# run test
+onecc -C ${configfile} > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/onecc_neg_029.cfg b/compiler/one-cmds/tests/onecc_neg_029.cfg
new file mode 100644
index 000000000..02f527b87
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_neg_029.cfg
@@ -0,0 +1,6 @@
+[onecc]
+one-codegen=True
+
+[one-codegen]
+backend=dummy3
+command=-o sample.tvn inception_v3.onecc_neg_029.circle
diff --git a/compiler/one-cmds/tests/onecc_neg_029.test b/compiler/one-cmds/tests/onecc_neg_029.test
new file mode 100644
index 000000000..5ced5fe67
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_neg_029.test
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# not found the command of given backend
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ if grep -q "Not found the command of given backend" "${filename}.log"; then
+ echo "${filename_ext} SUCCESS"
+ exit 0
+ fi
+
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="onecc_neg_029.cfg"
+
+rm -f ${filename}.log
+
+# run test
+onecc -C ${configfile} --backend dummy2 > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/onecc_neg_030.cfg b/compiler/one-cmds/tests/onecc_neg_030.cfg
new file mode 100644
index 000000000..0d573c1ad
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_neg_030.cfg
@@ -0,0 +1,6 @@
+[onecc]
+one-codegen=True
+
+[one-codegen]
+backends=dummy3
+dummy3=-o sample.tvn inception_v3.onecc_neg_030.circle
diff --git a/compiler/one-cmds/tests/onecc_neg_030.test b/compiler/one-cmds/tests/onecc_neg_030.test
new file mode 100644
index 000000000..404a9b885
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_neg_030.test
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# not found the command of given backend
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ if grep -q "Not found the command of given backend" "${filename}.log"; then
+ echo "${filename_ext} SUCCESS"
+ exit 0
+ fi
+
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="onecc_neg_030.cfg"
+
+rm -f ${filename}.log
+
+# run test
+onecc -C ${configfile} --backend dummy2 > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/onecc_neg_031.test b/compiler/one-cmds/tests/onecc_neg_031.test
new file mode 100644
index 000000000..c7d857562
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_neg_031.test
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# use 'backend' option with 'workflow' option
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ if grep -q "'backend' option can be used only with 'config' option" "${filename}.log"; then
+ echo "${filename_ext} SUCCESS"
+ exit 0
+ fi
+
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+workflowfile="onecc_neg_031.workflow.json"
+
+rm -f ${filename}.log
+
+# run test
+onecc -W ${workflowfile} --backend dummy > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/onecc_neg_031.workflow.json b/compiler/one-cmds/tests/onecc_neg_031.workflow.json
new file mode 100644
index 000000000..d323cc94f
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_neg_031.workflow.json
@@ -0,0 +1,29 @@
+{
+ "workflows": [
+ "codegen_wf"
+ ],
+ "codegen_wf": {
+ "steps": [
+ "import_tf",
+ "codegen"
+ ],
+ "import_tf": {
+ "one-cmd": "one-import-tf",
+ "commands": {
+ "input_path": "inception_v3.pb",
+ "output_path": "inception_v3.onecc_neg_031.circle",
+ "input_arrays": "input",
+ "input_shapes": "1,299,299,3",
+ "output_arrays": "InceptionV3/Predictions/Reshape_1",
+ "converter_version": "v2"
+ }
+ },
+ "codegen": {
+ "one-cmd": "one-codegen",
+ "commands": {
+ "backend": "dummy",
+ "command": "-o sample.tvn inception_v3.onecc_neg_031.circle"
+ }
+ }
+ }
+}
diff --git a/compiler/one-cmds/tests/onecc_neg_032.cfg b/compiler/one-cmds/tests/onecc_neg_032.cfg
new file mode 100644
index 000000000..949194806
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_neg_032.cfg
@@ -0,0 +1,7 @@
+[onecc]
+one-profile=True
+
+[one-profile]
+backends=dummy,dummyV2
+dummy=dummy.bin
+# dummyV2=dummyV2.bin
diff --git a/compiler/one-cmds/tests/onecc_neg_032.test b/compiler/one-cmds/tests/onecc_neg_032.test
new file mode 100644
index 000000000..12b70cbc4
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_neg_032.test
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# not found the command for given backend
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ if grep -q "Not found the command for dummyV2" "${filename}.log"; then
+ echo "${filename_ext} SUCCESS"
+ exit 0
+ fi
+
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="onecc_neg_032.cfg"
+
+rm -f ${filename}.log
+
+# run test
+onecc -C ${configfile} > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/onecc_neg_033.cfg b/compiler/one-cmds/tests/onecc_neg_033.cfg
new file mode 100644
index 000000000..6c77870b1
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_neg_033.cfg
@@ -0,0 +1,9 @@
+[onecc]
+one-profile=True
+
+[one-profile]
+backend=dummyV3
+command=dummyV3.bin
+backends=dummy,dummyV2
+dummy=dummy.bin
+dummyV2=dummyB2.bin
diff --git a/compiler/one-cmds/tests/onecc_neg_033.test b/compiler/one-cmds/tests/onecc_neg_033.test
new file mode 100644
index 000000000..51b7ca073
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_neg_033.test
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# use 'backend' and 'backends' option simultaneously
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ if grep -q "option cannot be used simultaneously" "${filename}.log"; then
+ echo "${filename_ext} SUCCESS"
+ exit 0
+ fi
+
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="onecc_neg_033.cfg"
+
+rm -f ${filename}.log
+
+# run test
+onecc -C ${configfile} > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/onecc_neg_034.cfg b/compiler/one-cmds/tests/onecc_neg_034.cfg
new file mode 100644
index 000000000..8c64628b4
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_neg_034.cfg
@@ -0,0 +1,6 @@
+[onecc]
+one-profile=True
+
+[one-profile]
+backend=dummy
+command=dummy.bin
diff --git a/compiler/one-cmds/tests/onecc_neg_034.test b/compiler/one-cmds/tests/onecc_neg_034.test
new file mode 100644
index 000000000..58cc8d3d1
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_neg_034.test
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# not found the command of given backend
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ if grep -q "Not found the command of given backend" "${filename}.log"; then
+ echo "${filename_ext} SUCCESS"
+ exit 0
+ fi
+
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="onecc_neg_034.cfg"
+
+rm -f ${filename}.log
+
+# run test
+onecc -C ${configfile} --backend dummyV2 > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/onecc_neg_035.cfg b/compiler/one-cmds/tests/onecc_neg_035.cfg
new file mode 100644
index 000000000..6468d73bc
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_neg_035.cfg
@@ -0,0 +1,6 @@
+[onecc]
+one-profile=True
+
+[one-profile]
+backends=dummyV2
+dummyV2=dummyV2.bin
diff --git a/compiler/one-cmds/tests/onecc_neg_035.test b/compiler/one-cmds/tests/onecc_neg_035.test
new file mode 100644
index 000000000..cae5ba1c8
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_neg_035.test
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# not found the command of given backend
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ if grep -q "Not found the command of given backend" "${filename}.log"; then
+ echo "${filename_ext} SUCCESS"
+ exit 0
+ fi
+
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="onecc_neg_035.cfg"
+
+rm -f ${filename}.log
+
+# run test
+onecc -C ${configfile} --backend dummy > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/onecc_neg_036.test b/compiler/one-cmds/tests/onecc_neg_036.test
new file mode 100644
index 000000000..929457575
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_neg_036.test
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# use 'backend' option with 'workflow' option
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ if grep -q "'backend' option can be used only with 'config' option" "${filename}.log"; then
+ echo "${filename_ext} SUCCESS"
+ exit 0
+ fi
+
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+workflowfile="onecc_neg_036.workflow.json"
+
+rm -f ${filename}.log
+
+# run test
+onecc -W ${workflowfile} --backend dummy > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/onecc_neg_036.workflow.json b/compiler/one-cmds/tests/onecc_neg_036.workflow.json
new file mode 100644
index 000000000..9acd4d26e
--- /dev/null
+++ b/compiler/one-cmds/tests/onecc_neg_036.workflow.json
@@ -0,0 +1,29 @@
+{
+ "workflows": [
+ "profile_wf"
+ ],
+ "profile_wf": {
+ "steps": [
+ "import_tf",
+ "profile"
+ ],
+ "import_tf": {
+ "one-cmd": "one-import-tf",
+ "commands": {
+ "input_path": "inception_v3.pb",
+ "output_path": "inception_v3.onecc_neg_036.circle",
+ "input_arrays": "input",
+ "input_shapes": "1,299,299,3",
+ "output_arrays": "InceptionV3/Predictions/Reshape_1",
+ "converter_version": "v2"
+ }
+ },
+ "profile": {
+ "one-cmd": "one-profile",
+ "commands": {
+ "backend": "dummy",
+ "command": "dummy.bin"
+ }
+ }
+ }
+}
diff --git a/compiler/one-cmds/tests/prepare_test_materials.sh b/compiler/one-cmds/tests/prepare_test_materials.sh
index 97bc6ebd2..915beff43 100644
--- a/compiler/one-cmds/tests/prepare_test_materials.sh
+++ b/compiler/one-cmds/tests/prepare_test_materials.sh
@@ -25,6 +25,10 @@ if [[ ! -s "inception_v3.pb" ]]; then
tar zxvf inception_v3_2018_04_27.tgz
fi
+if [[ ! -s "mobilenet_edgetpu_224_1.0_int8.tflite" ]]; then
+ wget -nv https://github.com/mlcommons/mobile_models/raw/main/v0_7/tflite/mobilenet_edgetpu_224_1.0_int8.tflite
+fi
+
if [[ ! -s "while_3.pbtxt" ]]; then
rm -rf while_3.zip
wget -nv https://github.com/Samsung/ONE/files/5095630/while_3.zip
@@ -93,9 +97,9 @@ fi
if [[ ! -s "reshape_matmul.onnx" ]]; then
rm -rf reshape_matmul.zip
- wget -nv https://github.com/Samsung/ONE/files/9082878/reshape_matmul.zip
+ wget -nv https://github.com/Samsung/ONE/files/12358217/reshape_matmul.zip
unzip reshape_matmul.zip
- # https://github.com/Samsung/ONE/issues/9405#issuecomment-1180198137
+ # https://github.com/Samsung/ONE/issues/9405#issuecomment-1680322410
fi
# prepare 'reshape_matmul.circle' file used for tests
@@ -175,4 +179,14 @@ if [[ ! -s ${outputfile} ]]; then
--output_path ${outputfile}
fi
+# prepare 'mobilenet_edgetpu_224_1.0_int8.circle' file used for requantization test
+inputfile="./mobilenet_edgetpu_224_1.0_int8.tflite"
+outputfile="./mobilenet_edgetpu_224_1.0_int8.circle"
+
+if [[ ! -s ${outputfile} ]]; then
+ ../bin/one-import-tflite \
+ --input_path ${inputfile} \
+ --output_path ${outputfile}
+fi
+
popd > /dev/null
diff --git a/compiler/one-cmds/tests/preprocess_images.py b/compiler/one-cmds/tests/preprocess_images.py
index 99991585d..ced6e3a08 100644
--- a/compiler/one-cmds/tests/preprocess_images.py
+++ b/compiler/one-cmds/tests/preprocess_images.py
@@ -26,8 +26,11 @@ for (root, _, files) in os.walk(input_dir):
datalist = open(list_file, 'w')
for f in files:
with PIL.Image.open(root + '/' + f) as image:
- img = np.array(image.resize((299, 299),
- PIL.Image.ANTIALIAS)).astype(np.float32)
+ # To handle ANTIALIAS deprecation
+ ANTIALIAS = PIL.Image.Resampling.LANCZOS if hasattr(
+ PIL.Image, "Resampling") else PIL.Image.ANTIALIAS
+
+ img = np.array(image.resize((299, 299), ANTIALIAS)).astype(np.float32)
img = ((img / 255) - 0.5) * 2.0
output_file = output_dir + '/' + f.replace('jpg', 'data')
img.tofile(output_file)
diff --git a/compiler/one-cmds/tests/pytorch-operations/example_generator.py b/compiler/one-cmds/tests/pytorch-operations/example_generator.py
index 20a80c895..2e3cdcf5b 100644
--- a/compiler/one-cmds/tests/pytorch-operations/example_generator.py
+++ b/compiler/one-cmds/tests/pytorch-operations/example_generator.py
@@ -17,7 +17,8 @@
# PyTorch Example manager
import torch
-import importlib
+import importlib.machinery
+import importlib.util
import argparse
import os
diff --git a/compiler/onecc-docker/docker/Dockerfile b/compiler/onecc-docker/docker/Dockerfile
index 975298527..ae912795a 100644
--- a/compiler/onecc-docker/docker/Dockerfile
+++ b/compiler/onecc-docker/docker/Dockerfile
@@ -19,8 +19,8 @@ ARG VERSION
RUN apt-get update && apt-get install -qqy --no-install-recommends \
wget \
ca-certificates \
- && wget https://github.com/Samsung/ONE/releases/download/${VERSION}/one-compiler_${VERSION}_amd64.deb \
- && apt-get install -y ./one-compiler_${VERSION}_amd64.deb \
+ && wget --no-check-certificate https://github.com/Samsung/ONE/releases/download/${VERSION}/one-compiler-bionic_${VERSION}_amd64.deb \
+ && apt-get install -y ./one-compiler-bionic_${VERSION}_amd64.deb \
&& rm -rf /var/lib/apt/lists/*
ENTRYPOINT ["onecc"]
diff --git a/compiler/onecc-docker/onecc-docker b/compiler/onecc-docker/onecc-docker
index ae3b31c4a..c68c7f1f3 100644
--- a/compiler/onecc-docker/onecc-docker
+++ b/compiler/onecc-docker/onecc-docker
@@ -16,17 +16,52 @@
import sys
import subprocess
-import json
import requests
import os
import argparse
+import re
-def _run(cmd, is_shell=False):
+class RequestHandler:
+ def __init__(self, token=None, timeout=None):
+ if token:
+ self.headers = {"Authorization": "Bearer {}".format(token)}
+ else:
+ self.headers = {}
+ self.timeout = timeout or 5
+
+ def make_request(self, url):
+ try:
+ response = requests.get(url, headers=self.headers, timeout=self.timeout)
+ response.raise_for_status()
+ return response
+ except requests.RequestException as e:
+ raise SystemExit('[onecc-docker] error: {}'.format(e))
+
+
+# 5 sec timeout is set based on github.com/Samsung/ONE/issues/11134
+def _request_recent_version(token=None):
+ response = RequestHandler(
+ token,
+ timeout=5).make_request(url="https://api.github.com/repos/Samsung/ONE/releases")
+ versions = [release_item["tag_name"] for release_item in response.json()]
+
+ for version in versions:
+ # Return the latest version with the given format
+ # to filter out such as 'onert-micro-0.1.0' release
+ # which doesn't contain onecc package.
+ if bool(re.match(r'^\d+\.\d+\.\d+$', version)):
+ return version
+
+ raise SystemExit('[onecc-docker] Failed to get latest onecc version')
+
+
+# 10 sec timeout is set based on github.com/Samsung/ONE/issues/11134
+def _run(cmd, is_shell=False, timeout=10):
result = subprocess.Popen(
cmd, shell=is_shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- stdout, stderr = result.communicate()
+ stdout, stderr = result.communicate(timeout=timeout)
stdout = stdout.decode('utf-8')
stderr = stderr.decode('utf-8')
@@ -61,20 +96,7 @@ def main():
args, onecc_arguments = parser.parse_known_args()
authorization_token = args.token
- LATEST_URL = "https://api.github.com/repos/Samsung/ONE/releases/latest"
- headers = {}
- if authorization_token:
- headers = {"Authorization": "Bearer {}".format(authorization_token)}
- try:
- response = requests.get(LATEST_URL, headers=headers)
- response.raise_for_status()
- except requests.exceptions.RequestException as e:
- raise SystemExit('onecc-docker: error: {}'.format(e))
-
- versions_str = response.content
- versions_json = json.loads(versions_str)
- recent_version = versions_json["tag_name"]
-
+ recent_version = _request_recent_version(authorization_token)
image_name = f"onecc:{recent_version}"
build_arg = f"VERSION={recent_version}"
@@ -82,9 +104,9 @@ def main():
build_cmd = [
"docker", "build", "-t", image_name, "--build-arg", build_arg, dockerfile_path
]
- print('build Docker image ...')
- _run(build_cmd)
- print('Dockerfile successfully built.')
+ print('[onecc-docker] Build docker image ...')
+ _run(build_cmd, timeout=30)
+ print('[onecc-docker] Docker image is built successfully.')
contianer_name = f"onecc_{recent_version.replace('.','_')}"
user_cmd = ' '.join(onecc_arguments)
diff --git a/compiler/oops/requires.cmake b/compiler/oops/requires.cmake
new file mode 100644
index 000000000..f68ab1638
--- /dev/null
+++ b/compiler/oops/requires.cmake
@@ -0,0 +1 @@
+require("pepper-str")
diff --git a/compiler/pics/CMakeLists.txt b/compiler/pics/CMakeLists.txt
index 80e6a1ca8..053d6a053 100644
--- a/compiler/pics/CMakeLists.txt
+++ b/compiler/pics/CMakeLists.txt
@@ -11,7 +11,7 @@ unset(PICS_DEPS)
###
set(CIRCLE_SCHEMA_PYTHON_DIR "${CMAKE_CURRENT_BINARY_DIR}/circle")
-get_target_property(SCHEMA_BIN_PATH mio_circle04 BINARY_DIR)
+get_target_property(SCHEMA_BIN_PATH mio_circle06 BINARY_DIR)
add_custom_command(
OUTPUT ${CIRCLE_SCHEMA_PYTHON_DIR}
diff --git a/compiler/pics/requires.cmake b/compiler/pics/requires.cmake
new file mode 100644
index 000000000..1b7745795
--- /dev/null
+++ b/compiler/pics/requires.cmake
@@ -0,0 +1 @@
+require("mio-circle06")
diff --git a/compiler/pota-quantization-value-test/CMakeLists.txt b/compiler/pota-quantization-value-test/CMakeLists.txt
index 53233cdd0..ec86fd907 100644
--- a/compiler/pota-quantization-value-test/CMakeLists.txt
+++ b/compiler/pota-quantization-value-test/CMakeLists.txt
@@ -6,6 +6,7 @@ unset(QUANTIZATION_VALUE_TEST)
unset(QUANTIZATION_VALUE_TEST_WITH_PARAM)
unset(QUANTIZATION_CONFIG_VALUE_TEST)
unset(QUANTIZATION_CONFIG_VALUE_TEST_WITH_PARAM)
+unset(QUANTIZATION_WO_VALUE_TEST_WITH_PARAM)
macro(addTest NAME GRANULARITY DTYPE)
list(APPEND QUANTIZATION_VALUE_TEST ${NAME})
@@ -17,6 +18,10 @@ macro(addQConfTest NAME GRANULARITY DTYPE)
list(APPEND QUANTIZATION_CONFIG_VALUE_TEST_WITH_PARAM ${NAME} ${GRANULARITY} ${DTYPE})
endmacro(addQConfTest)
+macro(addWeightsOnlyTest NAME GRANULARITY DTYPE)
+ list(APPEND QUANTIZATION_WO_VALUE_TEST_WITH_PARAM ${NAME} ${GRANULARITY} ${DTYPE})
+endmacro(addWeightsOnlyTest)
+
# Read "test.lst"
include("test.lst")
# Read "test.local.lst" if exists
@@ -29,12 +34,7 @@ get_target_property(ARTIFACTS_BIN_PATH testDataGenerator BINARY_DIR)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/gen_h5_explicit_inputs.py"
"${CMAKE_CURRENT_BINARY_DIR}/gen_h5_explicit_inputs.py" COPYONLY)
-# TODO Run both 2.8.0 and 2.10.1 test for jammy
-if(ONE_UBUNTU_CODENAME_JAMMY)
- set(VIRTUALENV "${NNCC_OVERLAY_DIR}/venv_2_10_1")
-else(ONE_UBUNTU_CODENAME_JAMMY)
- set(VIRTUALENV "${NNCC_OVERLAY_DIR}/venv_2_8_0")
-endif(ONE_UBUNTU_CODENAME_JAMMY)
+set(VIRTUALENV "${NNCC_OVERLAY_DIR}/venv_2_12_1")
###
### Generate test.config
@@ -114,6 +114,14 @@ add_test(
${QUANTIZATION_CONFIG_VALUE_TEST_WITH_PARAM}
)
+add_test(
+ NAME pota_wo_quantization_test
+ COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/test_wo_quantization.sh"
+ "${TEST_CONFIG}"
+ "${ARTIFACTS_BIN_PATH}"
+ ${QUANTIZATION_WO_VALUE_TEST_WITH_PARAM}
+)
+
set_tests_properties(pota_record_minmax_test PROPERTIES DEPENDS pota_fake_wquant_test)
set_tests_properties(pota_quantization_test PROPERTIES DEPENDS pota_record_minmax_test)
set_tests_properties(pota_parallel_record_minmax_test PROPERTIES DEPENDS pota_record_minmax_test)
diff --git a/compiler/pota-quantization-value-test/compare_tensors.py b/compiler/pota-quantization-value-test/compare_tensors.py
index 20e92c68b..fceeba547 100755
--- a/compiler/pota-quantization-value-test/compare_tensors.py
+++ b/compiler/pota-quantization-value-test/compare_tensors.py
@@ -19,7 +19,9 @@ parser.add_argument('--expect_dir', type=str, required=True)
parser.add_argument('--mode', type=str, required=True)
args = parser.parse_args()
-supported_modes = ["fake_quantization", "record_minmax", "quantization"]
+supported_modes = [
+ "fake_quantization", "record_minmax", "quantization", "weights_only_quantization"
+]
model = args.input_h5
expect_dir = args.expect_dir
@@ -111,6 +113,10 @@ with h5.File(model, "r") as input:
compare_record_minmax(input[tensor_name], tensor_name, expect_dir)
elif mode == "quantization":
compare_quantization(input[tensor_name], tensor_name, expect_dir)
+ elif mode == "weights_only_quantization":
+ # Assume weights have name "ker"
+ if tensor_name == "ker":
+ compare_quantization(input[tensor_name], tensor_name, expect_dir)
else:
raise SystemExit("Unsupproted mode.")
diff --git a/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/channel/int16/wo_quantization/ker.json b/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/channel/int16/wo_quantization/ker.json
new file mode 100644
index 000000000..94c794fbb
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/channel/int16/wo_quantization/ker.json
@@ -0,0 +1,61 @@
+{
+ "weights": [
+ [
+ [
+ [
+ 4096,
+ 8192
+ ],
+ [
+ -12288,
+ -16384
+ ]
+ ],
+ [
+ [
+ -20479,
+ 24575
+ ],
+ [
+ -28671,
+ 32767
+ ]
+ ]
+ ],
+ [
+ [
+ [
+ 16384,
+ -8192
+ ],
+ [
+ 12288,
+ -4096
+ ]
+ ],
+ [
+ [
+ -32767,
+ -24575
+ ],
+ [
+ 28671,
+ 20479
+ ]
+ ]
+ ]
+ ],
+ "scale": [
+ 0.00024414807580797754,
+ 0.00024414807580797754
+ ],
+ "zero_point": 0.0,
+ "min": [
+ -8.0,
+ -8.0
+ ],
+ "max": [
+ 8.0,
+ 8.0
+ ]
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/channel/int8/wo_quantization/ker.json b/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/channel/int8/wo_quantization/ker.json
new file mode 100644
index 000000000..6df116e65
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/Conv2D_004/channel/int8/wo_quantization/ker.json
@@ -0,0 +1,61 @@
+{
+ "weights": [
+ [
+ [
+ [
+ 16,
+ 32
+ ],
+ [
+ -48,
+ -64
+ ]
+ ],
+ [
+ [
+ -79,
+ 95
+ ],
+ [
+ -111,
+ 127
+ ]
+ ]
+ ],
+ [
+ [
+ [
+ 64,
+ -32
+ ],
+ [
+ 48,
+ -16
+ ]
+ ],
+ [
+ [
+ -127,
+ -95
+ ],
+ [
+ 111,
+ 79
+ ]
+ ]
+ ]
+ ],
+ "scale": [
+ 0.06299212574958801,
+ 0.06299212574958801
+ ],
+ "zero_point": 0.0,
+ "min": [
+ -8.0,
+ -8.0
+ ],
+ "max": [
+ 8.0,
+ 8.0
+ ]
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/channel/int16/wo_quantization/ker.json b/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/channel/int16/wo_quantization/ker.json
new file mode 100644
index 000000000..d465a7c17
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/channel/int16/wo_quantization/ker.json
@@ -0,0 +1,53 @@
+{
+ "weights": [
+ [
+ [
+ [
+ 2521,
+ 4681,
+ 6553,
+ 8192
+ ],
+ [
+ -22685,
+ 23405,
+ -24029,
+ 24575
+ ]
+ ],
+ [
+ [
+ 12603,
+ 14043,
+ 15291,
+ 16384
+ ],
+ [
+ 32767,
+ -32767,
+ 32767,
+ -32767
+ ]
+ ]
+ ]
+ ],
+ "scale": [
+ 0.0003967406231879635,
+ 0.0004272591326639607,
+ 0.0004577776421399579,
+ 0.0004882961516159551
+ ],
+ "zero_point": 0.0,
+ "min": [
+ -13.0,
+ -14.0,
+ -15.0,
+ -16.0
+ ],
+ "max": [
+ 13.0,
+ 14.0,
+ 15.0,
+ 16.0
+ ]
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/channel/int8/wo_quantization/ker.json b/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/channel/int8/wo_quantization/ker.json
new file mode 100644
index 000000000..13c929306
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/DepthwiseConv2D_002/channel/int8/wo_quantization/ker.json
@@ -0,0 +1,53 @@
+{
+ "weights": [
+ [
+ [
+ [
+ 10,
+ 18,
+ 25,
+ 32
+ ],
+ [
+ -88,
+ 91,
+ -93,
+ 95
+ ]
+ ],
+ [
+ [
+ 49,
+ 54,
+ 59,
+ 64
+ ],
+ [
+ 127,
+ -127,
+ 127,
+ -127
+ ]
+ ]
+ ]
+ ],
+ "scale": [
+ 0.10236220806837082,
+ 0.11023622006177902,
+ 0.11811023950576782,
+ 0.12598425149917603
+ ],
+ "zero_point": 0.0,
+ "min": [
+ -13.0,
+ -14.0,
+ -15.0,
+ -16.0
+ ],
+ "max": [
+ 13.0,
+ 14.0,
+ 15.0,
+ 16.0
+ ]
+}
diff --git a/compiler/pota-quantization-value-test/requires.cmake b/compiler/pota-quantization-value-test/requires.cmake
index e8acc81eb..e832dbaf7 100644
--- a/compiler/pota-quantization-value-test/requires.cmake
+++ b/compiler/pota-quantization-value-test/requires.cmake
@@ -2,5 +2,4 @@ require("record-minmax")
require("circle-quantizer")
require("circle-tensordump")
require("common-artifacts")
-require("mio-circle04")
require("pics")
diff --git a/compiler/pota-quantization-value-test/test.lst b/compiler/pota-quantization-value-test/test.lst
index e169de57c..e510e6b3b 100644
--- a/compiler/pota-quantization-value-test/test.lst
+++ b/compiler/pota-quantization-value-test/test.lst
@@ -60,3 +60,8 @@ addQConfTest(Split_000 channel uint8)
addQConfTest(Split_000 channel int16)
addQConfTest(TransposeConv_001 channel int16)
addQConfTest(TransposeConv_001 layer uint8)
+
+addWeightsOnlyTest(Conv2D_004 channel int8)
+addWeightsOnlyTest(Conv2D_004 channel int16)
+addWeightsOnlyTest(DepthwiseConv2D_002 channel int8)
+addWeightsOnlyTest(DepthwiseConv2D_002 channel int16)
diff --git a/compiler/pota-quantization-value-test/test_wo_quantization.sh b/compiler/pota-quantization-value-test/test_wo_quantization.sh
new file mode 100755
index 000000000..18c85fe75
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_wo_quantization.sh
@@ -0,0 +1,87 @@
+#!/bin/bash
+
+# This script tests the basic behavior of weights-only quantization
+#
+# HOW TO USE
+#
+# ./test_quantization.sh <path/to/test.config> <path/to/work_dir> <TEST 1> <TEST 2> ...
+# test.config : set ${CIRCLE_QUANTIZER_PATH} and ${CIRCLE_TENSORDUMP_PATH}"
+# work_dir : build directory of quantization-value-test (ex: build/compiler/quantization-value-test)
+
+SOURCE_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+COMPARE_SCRIPT_PATH="${SOURCE_PATH}/compare_tensors.py"
+CONFIG_PATH="$1"; shift
+BIN_PATH=$(dirname "${CONFIG_PATH}")
+TEST_INPUT_PATH="${SOURCE_PATH}/test_inputs"
+WORKDIR="$1"; shift
+
+source "${CONFIG_PATH}"
+
+echo "-- Found CIRCLE_QUANTIZER: ${CIRCLE_QUANTIZER_PATH}"
+echo "-- Found CIRCLE_TENSORDUMP: ${CIRCLE_TENSORDUMP_PATH}"
+echo "-- Found workdir: ${WORKDIR}"
+
+TESTED=()
+PASSED=()
+FAILED=()
+
+pushd "${WORKDIR}"
+while [ "$1" != "" ]; do
+ MODELNAME=$1; shift
+ GRANULARITY=$1; shift
+ DTYPE=$1; shift
+ TESTCASE="${MODELNAME}.${GRANULARITY}.${DTYPE}"
+
+ TESTED+=("${TESTCASE}")
+
+ TESTCASE_FILE="${WORKDIR}/${TESTCASE}"
+ TEST_RESULT_FILE="${BIN_PATH}/${TESTCASE}"
+
+ PASSED_TAG="${TEST_RESULT_FILE}.wo_quantization.passed"
+ rm -f "${PASSED_TAG}"
+
+ cat > "${TEST_RESULT_FILE}_wo_quantization.log" <(
+ exec 2>&1
+ set -ex
+
+ # Run circle-quantizer with --quantize_weights
+ "${CIRCLE_QUANTIZER_PATH}" \
+ --quantize_weights float32 "${DTYPE}" "${GRANULARITY}" \
+ "${WORKDIR}/${MODELNAME}.circle" \
+ "${TEST_RESULT_FILE}.wo_quantized.circle"
+
+ # Dump scale, zp, weights values (circle-tensordump)
+ "${CIRCLE_TENSORDUMP_PATH}" \
+ "${TEST_RESULT_FILE}.wo_quantized.circle" \
+ --tensors_to_hdf5 "${TEST_RESULT_FILE}.wo_quantized.circle.h5"
+
+ # Compare result
+ "${VIRTUALENV}/bin/python" "${COMPARE_SCRIPT_PATH}" \
+ --input_h5 "${TEST_RESULT_FILE}.wo_quantized.circle.h5" \
+ --expect_dir "${SOURCE_PATH}/expected_outputs/${MODELNAME}/${GRANULARITY}/${DTYPE}/wo_quantization" \
+ --mode weights_only_quantization
+
+ if [[ $? -eq 0 ]]; then
+ touch "${PASSED_TAG}"
+ fi
+ )
+
+ if [[ -f "${PASSED_TAG}" ]]; then
+ PASSED+=("$TESTCASE")
+ else
+ FAILED+=("$TESTCASE")
+ fi
+done
+popd
+
+if [[ ${#TESTED[@]} -ne ${#PASSED[@]} ]]; then
+ echo "FAILED"
+ for TEST in "${FAILED[@]}"
+ do
+ echo "- ${TEST}"
+ done
+ exit 255
+fi
+
+echo "PASSED"
+exit 0
diff --git a/compiler/record-minmax-conversion-test/CMakeLists.txt b/compiler/record-minmax-conversion-test/CMakeLists.txt
index 63fe33d98..35a7f9908 100644
--- a/compiler/record-minmax-conversion-test/CMakeLists.txt
+++ b/compiler/record-minmax-conversion-test/CMakeLists.txt
@@ -41,17 +41,6 @@ add_test(
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/testall.sh"
"${TEST_CONFIG}"
"${ARTIFACTS_BIN_PATH}"
- "${NNCC_OVERLAY_DIR}/venv_2_8_0"
+ "${NNCC_OVERLAY_DIR}/venv_2_12_1"
${RECORD_MINMAX_CONVERSION_TEST}
)
-
-if(ONE_UBUNTU_CODENAME_JAMMY)
- add_test(
- NAME record_minmax_conversion_210_test
- COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/testall.sh"
- "${TEST_CONFIG}"
- "${ARTIFACTS_BIN_PATH}"
- "${NNCC_OVERLAY_DIR}/venv_2_10_1"
- ${RECORD_MINMAX_CONVERSION_TEST}
- )
-endif(ONE_UBUNTU_CODENAME_JAMMY)
diff --git a/compiler/record-minmax-thread-safety-test/CMakeLists.txt b/compiler/record-minmax-thread-safety-test/CMakeLists.txt
index ba0f0820c..9d25ac37e 100644
--- a/compiler/record-minmax-thread-safety-test/CMakeLists.txt
+++ b/compiler/record-minmax-thread-safety-test/CMakeLists.txt
@@ -2,6 +2,12 @@ if(NOT ENABLE_TEST)
return()
endif(NOT ENABLE_TEST)
+# Disable the test if record-minmax-for-thread-test does not exist
+if (NOT TARGET record-minmax-for-thread-test)
+ message(STATUS "record-minmax-thread-safety-test is disabled as record-minmax-for-thread-test was not built.")
+ return()
+endif(NOT TARGET record-minmax-for-thread-test)
+
# Build record-minmax-for-thread-test if target arch is 64bit
# Thread sanitizer is only available on 64bit machine
# (https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual#supported-platforms)
@@ -57,17 +63,6 @@ add_test(
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/testall.sh"
"${TEST_CONFIG}"
"${ARTIFACTS_BIN_PATH}"
- "${NNCC_OVERLAY_DIR}/venv_2_8_0"
+ "${NNCC_OVERLAY_DIR}/venv_2_12_1"
${RECORD_MINMAX_THREAD_SAFETY_TEST}
)
-
-if(ONE_UBUNTU_CODENAME_JAMMY)
- add_test(
- NAME record_minmax_thread_safety_210_test
- COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/testall.sh"
- "${TEST_CONFIG}"
- "${ARTIFACTS_BIN_PATH}"
- "${NNCC_OVERLAY_DIR}/venv_2_10_1"
- ${RECORD_MINMAX_THREAD_SAFETY_TEST}
- )
-endif(ONE_UBUNTU_CODENAME_JAMMY)
diff --git a/compiler/record-minmax/CMakeLists.txt b/compiler/record-minmax/CMakeLists.txt
index 391e35b7f..3feca330a 100644
--- a/compiler/record-minmax/CMakeLists.txt
+++ b/compiler/record-minmax/CMakeLists.txt
@@ -23,11 +23,17 @@ if(NOT ENABLE_TEST)
return()
endif(NOT ENABLE_TEST)
+###
+### record-minmax-for-thread-test is temporarily disabled, because
+### gcc package has a bug.
+### (https://bugs.launchpad.net/ubuntu/+source/gcc-10/+bug/2029910)
+### Let's enable the target after the bug is fixed.
+###
# Build record-minmax-for-thread-test if target arch is 64bit
# Thread sanitizer is only available on 64bit machine
# (https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual#supported-platforms)
-if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
- # create record-minmax-for-thread-test target
+if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8" AND FALSE)
+# create record-minmax-for-thread-test target
# Note: record-minmax-for-thread-test is built with -fsanitize=thread so that thread sanitizer can check memory bugs,
# record-minmax is built without the option for performance.
add_executable(record-minmax-for-thread-test ${DRIVER} ${SOURCES})
@@ -46,11 +52,18 @@ if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
target_compile_options(record-minmax-for-thread-test PUBLIC -fsanitize=thread)
target_link_libraries(record-minmax-for-thread-test -fsanitize=thread)
-endif("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
+endif("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8" AND FALSE)
+
+# record-minmax is executable, so we do not link it to the test.
+# Instead, we use TEST_SOURCES to specify sources uesd for tests.
+set(TEST_SOURCES
+ "src/RecordFunction.cpp"
+ "src/MinMaxComputer.cpp")
file(GLOB_RECURSE TESTS "tests/*.test.cpp")
nnas_find_package(GTest REQUIRED)
-GTest_AddTest(record_minmax_function_test "${TESTS}")
+GTest_AddTest(record_minmax_function_test ${TESTS} ${TEST_SOURCES})
target_include_directories(record_minmax_function_test PRIVATE include)
+target_link_libraries(record_minmax_function_test luci_lang)
target_link_libraries(record_minmax_function_test nncc_coverage)
diff --git a/compiler/record-minmax/driver/Driver.cpp b/compiler/record-minmax/driver/Driver.cpp
index d8ed95e9a..24a4ff80f 100644
--- a/compiler/record-minmax/driver/Driver.cpp
+++ b/compiler/record-minmax/driver/Driver.cpp
@@ -63,6 +63,15 @@ int entry(const int argc, char **argv)
.type(arser::DataType::FLOAT)
.help("Record n'th percentile of max");
+ arser.add_argument("--moving_avg_batch")
+ .type(arser::DataType::INT32)
+ .help("Batch size of moving average algorithm (default: 16)");
+
+ arser.add_argument("--moving_avg_const")
+ .type(arser::DataType::FLOAT)
+ .help("Hyperparameter (C) to compute moving average (default: 0.1). Update equation: avg <- "
+ "avg + C * (curr_batch_avg - avg)");
+
arser.add_argument("--mode").help("Record mode. percentile (default) or moving_average");
arser.add_argument("--input_data_format")
@@ -100,6 +109,8 @@ int entry(const int argc, char **argv)
std::string mode("percentile");
float min_percentile = 1.0;
float max_percentile = 99.0;
+ uint32_t moving_avg_batch = 16;
+ float moving_avg_const = 0.1;
std::string input_data_format("h5");
uint32_t num_threads = 1;
@@ -118,6 +129,12 @@ int entry(const int argc, char **argv)
if (arser["--mode"])
mode = arser.get<std::string>("--mode");
+ if (arser["--moving_avg_batch"])
+ moving_avg_batch = arser.get<int>("--moving_avg_batch");
+
+ if (arser["--moving_avg_const"])
+ moving_avg_const = arser.get<float>("--moving_avg_const");
+
if (mode != "percentile" && mode != "moving_average")
throw std::runtime_error("Unsupported mode");
@@ -127,7 +144,23 @@ int entry(const int argc, char **argv)
if (arser["--input_data_format"])
input_data_format = arser.get<std::string>("--input_data_format");
- RecordMinMax rmm(num_threads);
+ std::unique_ptr<MinMaxComputer> computer;
+ {
+ if (mode == "percentile")
+ {
+ computer = make_percentile_computer(min_percentile, max_percentile);
+ }
+ else if (mode == "moving_average")
+ {
+ computer = make_moving_avg_computer(moving_avg_batch, moving_avg_const);
+ }
+ else
+ {
+ assert(false);
+ }
+ }
+
+ RecordMinMax rmm(num_threads, std::move(computer));
// TODO: support parallel record for profile with random data
if (num_threads > 1 and not arser["--input_data"])
@@ -152,11 +185,11 @@ int entry(const int argc, char **argv)
{
// Profile min/max while executing the H5 data
if (num_threads == 1)
- rmm.profileData(mode, input_data_path, min_percentile, max_percentile);
+ rmm.profileData(input_data_path);
else
{
INFO(l) << "Using parallel recording" << std::endl;
- rmm.profileDataInParallel(mode, input_data_path, min_percentile, max_percentile);
+ rmm.profileDataInParallel(input_data_path);
}
}
// input_data is a text file having a file path in each line.
@@ -170,13 +203,13 @@ int entry(const int argc, char **argv)
else if (input_data_format == "list" || input_data_format == "filelist")
{
// Profile min/max while executing the list of Raw data
- rmm.profileRawData(mode, input_data_path, min_percentile, max_percentile);
+ rmm.profileRawData(input_data_path);
}
else if (input_data_format == "directory" || input_data_format == "dir")
{
// Profile min/max while executing all files under the given directory
// The contents of each file is same as the raw data in the 'list' type
- rmm.profileRawDataDirectory(mode, input_data_path, min_percentile, max_percentile);
+ rmm.profileRawDataDirectory(input_data_path);
}
else
{
@@ -187,7 +220,7 @@ int entry(const int argc, char **argv)
else
{
// Profile min/max while executing random input data
- rmm.profileDataWithRandomInputs(mode, min_percentile, max_percentile);
+ rmm.profileDataWithRandomInputs();
}
// Save profiled values to the model
diff --git a/compiler/record-minmax/include/MinMaxComputer.h b/compiler/record-minmax/include/MinMaxComputer.h
new file mode 100644
index 000000000..0e9c8881b
--- /dev/null
+++ b/compiler/record-minmax/include/MinMaxComputer.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __RECORD_MINMAX_MINMAXCOMPUTER_H__
+#define __RECORD_MINMAX_MINMAXCOMPUTER_H__
+
+#include "MinMaxVectors.h"
+
+#include <luci/IR/CircleNode.h>
+
+#include <unordered_map>
+#include <memory>
+
+namespace record_minmax
+{
+
+class MinMaxComputer
+{
+public:
+ MinMaxComputer()
+ {
+ // Do nothing
+ }
+
+ virtual ~MinMaxComputer() = default;
+
+ // Child class must implement this
+ virtual void
+ update_qparam(const std::unordered_map<const luci::CircleNode *, MinMaxVectors> *minmax_map) = 0;
+};
+
+class PercentileComputer : public MinMaxComputer
+{
+public:
+ PercentileComputer(float min_percentile, float max_percentile)
+ : _min_percentile(min_percentile), _max_percentile(max_percentile)
+ {
+ }
+
+ virtual void
+ update_qparam(const std::unordered_map<const luci::CircleNode *, MinMaxVectors> *minmax_map);
+
+private:
+ float _min_percentile = 0.0;
+ float _max_percentile = 0.0;
+};
+
+class MovingAvgComputer : public MinMaxComputer
+{
+public:
+ MovingAvgComputer(uint32_t batch_size, float update_const)
+ : _batch_size(batch_size), _update_const(update_const)
+ {
+ }
+
+ virtual void
+ update_qparam(const std::unordered_map<const luci::CircleNode *, MinMaxVectors> *minmax_map);
+
+private:
+ uint32_t _batch_size = 0;
+ float _update_const = 0.0;
+};
+
+std::unique_ptr<MinMaxComputer> make_percentile_computer(float min_percentile,
+ float max_percentile);
+
+std::unique_ptr<MinMaxComputer> make_moving_avg_computer(uint32_t batch_size,
+ float moving_avg_const);
+
+} // namespace record_minmax
+
+#endif // __RECORD_MINMAX_MINMAXCOMPUTER_H__
diff --git a/compiler/record-minmax/include/MinMaxObserver.h b/compiler/record-minmax/include/MinMaxObserver.h
index c34ac8ea8..f0167971f 100644
--- a/compiler/record-minmax/include/MinMaxObserver.h
+++ b/compiler/record-minmax/include/MinMaxObserver.h
@@ -20,18 +20,14 @@
#include <luci_interpreter/Interpreter.h>
#include <luci_interpreter/core/Tensor.h>
+#include "MinMaxVectors.h"
+
#include <vector>
#include <unordered_map>
namespace record_minmax
{
-struct MinMaxVectors
-{
- std::vector<float> min_vector;
- std::vector<float> max_vector;
-};
-
class MinMaxMap
{
public:
@@ -72,6 +68,7 @@ public:
void postTensorWrite(const luci::CircleNode *node,
const luci_interpreter::Tensor *tensor) override;
+ // Never return nullptr
const MinMaxMap *minMaxData() { return &_minmax_data; }
private:
diff --git a/compiler/record-minmax/include/MinMaxVectors.h b/compiler/record-minmax/include/MinMaxVectors.h
new file mode 100644
index 000000000..5b2b03a34
--- /dev/null
+++ b/compiler/record-minmax/include/MinMaxVectors.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __RECORD_MINMAX_MINMAXVECTORS_H__
+#define __RECORD_MINMAX_MINMAXVECTORS_H__
+
+#include <vector>
+
+namespace record_minmax
+{
+
+struct MinMaxVectors
+{
+ std::vector<float> min_vector;
+ std::vector<float> max_vector;
+};
+
+} // namespace record_minmax
+
+#endif // __RECORD_MINMAX_MINMAXVECTORS_H__
diff --git a/compiler/record-minmax/include/RecordFunction.h b/compiler/record-minmax/include/RecordFunction.h
index d5da01ce0..745ee2282 100644
--- a/compiler/record-minmax/include/RecordFunction.h
+++ b/compiler/record-minmax/include/RecordFunction.h
@@ -14,12 +14,11 @@
* limitations under the License.
*/
+#ifndef __RECORD_MINMAX_RECORD_FUNCTION_H__
+#define __RECORD_MINMAX_RECORD_FUNCTION_H__
+
#include <vector>
-#include <cassert>
-#include <algorithm>
-#include <cmath>
-#include <limits>
-#include <stdexcept>
+#include <cstdint>
namespace record_minmax
{
@@ -28,75 +27,15 @@ namespace record_minmax
* @brief getNthPercentile calculates the n-th percentile of input vector (0.0 <= n <= 100.0)
* linear interpolation is used when the desired percentile lies between two data points
*/
-float getNthPercentile(std::vector<float> &vector, float percentile)
-{
- if (percentile < 0 || percentile > 100)
- throw std::runtime_error("Percentile must be ranged from 0 to 100");
-
- if (vector.empty())
- throw std::runtime_error("Percentile must take a non-empty vector as an argument");
-
- if (vector.size() == 1)
- return vector[0];
-
- std::vector<float> copy;
- copy.assign(vector.begin(), vector.end());
- std::sort(copy.begin(), copy.end());
-
- if (percentile == 0.0)
- return copy.front();
-
- if (percentile == 100.0)
- return copy.back();
-
- int index = static_cast<int>(std::floor((copy.size() - 1) * percentile / 100.0));
-
- float percent_i = static_cast<float>(index) / static_cast<float>(copy.size() - 1);
- float fraction =
- (percentile / 100.0 - percent_i) / ((index + 1.0) / (copy.size() - 1.0) - percent_i);
- float res = copy[index] + fraction * (copy[index + 1] - copy[index]);
- return res;
-}
+float getNthPercentile(std::vector<float> &vector, float percentile);
/**
* @brief getMovingAverage calculates the weighted moving average of input vector
* The initial value is the minimum (or maximum) value of the first batch of the vector
*/
float getMovingAverage(const std::vector<float> &vector, const float alpha,
- const uint8_t batch_size, bool is_min)
-{
- assert(!vector.empty());
- assert(alpha >= 0.0 && alpha <= 1.0);
- assert(batch_size > 0);
-
- auto getBatchMinOrMax = [&](uint32_t start_index) {
- assert(start_index < vector.size());
-
- float res = is_min ? std::numeric_limits<float>::max() : std::numeric_limits<float>::lowest();
- for (uint32_t offset = 0; offset < batch_size; offset++)
- {
- uint32_t index = start_index + offset;
- if (index >= vector.size())
- break;
-
- if (is_min)
- {
- res = vector[index] < res ? vector[index] : res;
- }
- else
- {
- res = vector[index] > res ? vector[index] : res;
- }
- }
- return res;
- };
-
- float curr_avg = getBatchMinOrMax(0);
- for (uint32_t i = batch_size; i < vector.size(); i += batch_size)
- {
- curr_avg = curr_avg * alpha + getBatchMinOrMax(i) * (1.0 - alpha);
- }
- return curr_avg;
-}
+ const uint8_t batch_size, bool is_min);
} // namespace record_minmax
+
+#endif // __RECORD_MINMAX_RECORD_FUNCTION_H__
diff --git a/compiler/record-minmax/include/RecordMinMax.h b/compiler/record-minmax/include/RecordMinMax.h
index 2a7b88f1f..758e8a924 100644
--- a/compiler/record-minmax/include/RecordMinMax.h
+++ b/compiler/record-minmax/include/RecordMinMax.h
@@ -21,6 +21,7 @@
#include <luci_interpreter/Interpreter.h>
#include "MinMaxObserver.h"
+#include "MinMaxComputer.h"
#include <memory>
#include <thread>
@@ -35,35 +36,40 @@ using WholeOutput = std::vector<Output>;
class RecordMinMax
{
public:
- explicit RecordMinMax(uint32_t num_threads) : _threads_size(num_threads)
+ explicit RecordMinMax(uint32_t num_threads, std::unique_ptr<MinMaxComputer> &&minmax_computer)
+ : _threads_size(num_threads), _minmax_computer(std::move(minmax_computer))
{
assert(_threads_size > 0);
+ assert(_minmax_computer != nullptr);
}
~RecordMinMax() = default;
void initialize(const std::string &input_model_path);
- void profileData(const std::string &mode, const std::string &input_data_path,
- float min_percentile, float max_percentile);
+ // TODO Refactor profile functions
+ void profileData(const std::string &input_data_path);
- void profileDataInParallel(const std::string &mode, const std::string &input_data_path,
- float min_percentile, float max_percentile);
+ void profileDataInParallel(const std::string &input_data_path);
- void profileRawData(const std::string &mode, const std::string &input_data_path,
- float min_percentile, float max_percentile);
+ void profileRawData(const std::string &input_data_path);
- void profileRawDataDirectory(const std::string &mode, const std::string &input_data_path,
- float min_percentile, float max_percentile);
+ void profileRawDataDirectory(const std::string &input_data_path);
- void profileDataWithRandomInputs(const std::string &mode, float min_percentile,
- float max_percentile);
+ void profileDataWithRandomInputs(void);
void saveModel(const std::string &output_model_path);
private:
luci_interpreter::Interpreter *getInterpreter() const { return _interpreters[0].get(); }
- MinMaxObserver *getObserver() const { return _observers[0].get(); }
+
+ // Never return nullptr
+ MinMaxObserver *getObserver() const
+ {
+ assert(_observers.size() > 0); // FIX CALLER UNLESS
+ assert(_observers[0].get()); // FIX CALLER UNLESS
+ return _observers[0].get();
+ }
WholeOutput importH5Data(const std::string &input_data_path);
@@ -74,6 +80,7 @@ private:
std::vector<std::unique_ptr<MinMaxObserver>> _observers;
uint32_t _threads_size = 0;
+ std::unique_ptr<MinMaxComputer> _minmax_computer;
};
} // namespace record_minmax
diff --git a/compiler/record-minmax/src/MinMaxComputer.cpp b/compiler/record-minmax/src/MinMaxComputer.cpp
new file mode 100644
index 000000000..5b8893a50
--- /dev/null
+++ b/compiler/record-minmax/src/MinMaxComputer.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MinMaxComputer.h"
+#include "RecordFunction.h"
+
+#include <luci/IR/CircleQuantParam.h>
+
+namespace record_minmax
+{
+
+void PercentileComputer::update_qparam(
+ const std::unordered_map<const luci::CircleNode *, MinMaxVectors> *minmax_map)
+{
+ if (minmax_map == nullptr)
+ throw std::invalid_argument("minmax_map is nullptr");
+
+ for (auto iter = minmax_map->begin(); iter != minmax_map->end(); ++iter)
+ {
+ auto node = iter->first;
+ auto minmax = iter->second;
+
+ auto min = getNthPercentile(minmax.min_vector, _min_percentile);
+ auto max = getNthPercentile(minmax.max_vector, _max_percentile);
+
+ auto quantparam = std::make_unique<luci::CircleQuantParam>();
+ quantparam->min.push_back(min);
+ quantparam->max.push_back(max);
+
+ assert(node->quantparam() == nullptr);
+
+ auto mutable_node = const_cast<luci::CircleNode *>(node);
+ mutable_node->quantparam(std::move(quantparam));
+ }
+}
+
+void MovingAvgComputer::update_qparam(
+ const std::unordered_map<const luci::CircleNode *, MinMaxVectors> *minmax_map)
+{
+ if (minmax_map == nullptr)
+ throw std::invalid_argument("minmax_map is nullptr");
+
+ for (auto iter = minmax_map->begin(); iter != minmax_map->end(); ++iter)
+ {
+ auto node = iter->first;
+ auto minmax = iter->second;
+
+ auto min = getMovingAverage(minmax.min_vector, 1 - _update_const, _batch_size, true);
+ auto max = getMovingAverage(minmax.max_vector, 1 - _update_const, _batch_size, false);
+
+ auto quantparam = std::make_unique<luci::CircleQuantParam>();
+ quantparam->min.push_back(min);
+ quantparam->max.push_back(max);
+
+ assert(node->quantparam() == nullptr);
+
+ auto mutable_node = const_cast<luci::CircleNode *>(node);
+ mutable_node->quantparam(std::move(quantparam));
+ }
+}
+
+std::unique_ptr<MinMaxComputer> make_percentile_computer(float min_percentile, float max_percentile)
+{
+ return std::make_unique<PercentileComputer>(min_percentile, max_percentile);
+}
+
+std::unique_ptr<MinMaxComputer> make_moving_avg_computer(uint32_t batch_size,
+ float moving_avg_const)
+{
+ return std::make_unique<MovingAvgComputer>(batch_size, moving_avg_const);
+}
+
+} // namespace record_minmax
diff --git a/compiler/record-minmax/src/RecordFunction.cpp b/compiler/record-minmax/src/RecordFunction.cpp
new file mode 100644
index 000000000..e812f82f3
--- /dev/null
+++ b/compiler/record-minmax/src/RecordFunction.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "RecordFunction.h"
+
+#include <luci/IR/CircleQuantParam.h>
+
+#include <cassert>
+#include <algorithm>
+#include <cmath>
+#include <limits>
+#include <stdexcept>
+
+namespace record_minmax
+{
+
+float getNthPercentile(std::vector<float> &vector, float percentile)
+{
+ if (percentile < 0 || percentile > 100)
+ throw std::runtime_error("Percentile must be ranged from 0 to 100");
+
+ if (vector.empty())
+ throw std::runtime_error("Percentile must take a non-empty vector as an argument");
+
+ if (vector.size() == 1)
+ return vector[0];
+
+ std::vector<float> copy;
+ copy.assign(vector.begin(), vector.end());
+ std::sort(copy.begin(), copy.end());
+
+ if (percentile == 0.0)
+ return copy.front();
+
+ if (percentile == 100.0)
+ return copy.back();
+
+ int index = static_cast<int>(std::floor((copy.size() - 1) * percentile / 100.0));
+
+ float percent_i = static_cast<float>(index) / static_cast<float>(copy.size() - 1);
+ float fraction =
+ (percentile / 100.0 - percent_i) / ((index + 1.0) / (copy.size() - 1.0) - percent_i);
+ float res = copy[index] + fraction * (copy[index + 1] - copy[index]);
+ return res;
+}
+
+float getMovingAverage(const std::vector<float> &vector, const float alpha,
+ const uint8_t batch_size, bool is_min)
+{
+ assert(!vector.empty());
+ assert(alpha >= 0.0 && alpha <= 1.0);
+ assert(batch_size > 0);
+
+ auto getBatchMinOrMax = [&](uint32_t start_index) {
+ assert(start_index < vector.size());
+
+ float res = is_min ? std::numeric_limits<float>::max() : std::numeric_limits<float>::lowest();
+ for (uint32_t offset = 0; offset < batch_size; offset++)
+ {
+ uint32_t index = start_index + offset;
+ if (index >= vector.size())
+ break;
+
+ if (is_min)
+ {
+ res = vector[index] < res ? vector[index] : res;
+ }
+ else
+ {
+ res = vector[index] > res ? vector[index] : res;
+ }
+ }
+ return res;
+ };
+
+ float curr_avg = getBatchMinOrMax(0);
+ for (uint32_t i = batch_size; i < vector.size(); i += batch_size)
+ {
+ curr_avg = curr_avg * alpha + getBatchMinOrMax(i) * (1.0 - alpha);
+ }
+ return curr_avg;
+}
+
+} // namespace record_minmax
diff --git a/compiler/record-minmax/src/RecordMinMax.cpp b/compiler/record-minmax/src/RecordMinMax.cpp
index c3da83a5d..d96b79c34 100644
--- a/compiler/record-minmax/src/RecordMinMax.cpp
+++ b/compiler/record-minmax/src/RecordMinMax.cpp
@@ -15,7 +15,6 @@
*/
#include "RecordMinMax.h"
-#include "RecordFunction.h"
#include "MinMaxObserver.h"
#include <luci/Importer.h>
@@ -144,38 +143,6 @@ void verifyTypeShape(const luci::CircleInput *input_node, const DataType &dtype,
}
}
-void update_quantparam(record_minmax::MinMaxObserver *observer, const std::string &mode,
- float min_percentile, float max_percentile)
-{
- auto minmax_map = observer->minMaxData()->getMap();
- for (auto iter = minmax_map->begin(); iter != minmax_map->end(); ++iter)
- {
- auto node = iter->first;
- auto minmax = iter->second;
-
- float min{0.0f}, max{0.0f};
- if (mode == "percentile")
- {
- min = record_minmax::getNthPercentile(minmax.min_vector, min_percentile);
- max = record_minmax::getNthPercentile(minmax.max_vector, max_percentile);
- }
- else if (mode == "moving_average")
- {
- min = record_minmax::getMovingAverage(minmax.min_vector, 0.9, 16, true);
- max = record_minmax::getMovingAverage(minmax.max_vector, 0.9, 16, false);
- }
- assert(mode == "percentile" || mode == "moving_average");
- auto quantparam = std::make_unique<luci::CircleQuantParam>();
- quantparam->min.push_back(min);
- quantparam->max.push_back(max);
-
- assert(node->quantparam() == nullptr);
-
- auto mutable_node = const_cast<luci::CircleNode *>(node);
- mutable_node->quantparam(std::move(quantparam));
- }
-}
-
} // namespace
namespace record_minmax
@@ -235,9 +202,7 @@ void RecordMinMax::initialize(const std::string &input_model_path)
// The directory should contain binary files each of which is a raw data,
// ready to be consumed by the input circle model without any modification
// TODO reduce duplicate codes with profileRawData
-void RecordMinMax::profileRawDataDirectory(const std::string &mode,
- const std::string &input_data_path, float min_percentile,
- float max_percentile)
+void RecordMinMax::profileRawDataDirectory(const std::string &input_data_path)
{
struct dirent *entry = nullptr;
DIR *dp = nullptr;
@@ -297,7 +262,7 @@ void RecordMinMax::profileRawDataDirectory(const std::string &mode,
std::cout << "Recording finished. Number of recorded data: " << num_records << std::endl;
- update_quantparam(getObserver(), mode, min_percentile, max_percentile);
+ _minmax_computer->update_qparam(getObserver()->minMaxData()->getMap());
}
// input_data_path is a text file which specifies the representative data
@@ -306,8 +271,7 @@ void RecordMinMax::profileRawDataDirectory(const std::string &mode,
// ready to be consumed by the input circle model without any modification
// NOTE If a model has multiple inputs, the binary file should have inputs concatenated in the same
// order with the input index of the circle model.
-void RecordMinMax::profileRawData(const std::string &mode, const std::string &input_data_path,
- float min_percentile, float max_percentile)
+void RecordMinMax::profileRawData(const std::string &input_data_path)
{
std::ifstream input_file(input_data_path);
if (input_file.fail())
@@ -357,7 +321,7 @@ void RecordMinMax::profileRawData(const std::string &mode, const std::string &in
std::cout << "Recording finished. Number of recorded data: " << num_records << std::endl;
- update_quantparam(getObserver(), mode, min_percentile, max_percentile);
+ _minmax_computer->update_qparam(getObserver()->minMaxData()->getMap());
}
WholeOutput RecordMinMax::importH5Data(const std::string &input_data_path)
@@ -395,7 +359,7 @@ WholeOutput RecordMinMax::importH5Data(const std::string &input_data_path)
{
DataType dtype;
Shape shape;
- importer.readTensor(i, input_idx, &dtype, &shape, input_data.data());
+ importer.readTensor(i, input_idx, &dtype, &shape, input_data.data(), input_data.size());
// Check the type and the shape of the input data is valid
verifyTypeShape(input_node, dtype, shape);
@@ -403,7 +367,7 @@ WholeOutput RecordMinMax::importH5Data(const std::string &input_data_path)
else
{
// Skip type/shape check for raw data
- importer.readTensor(i, input_idx, input_data.data());
+ importer.readTensor(i, input_idx, input_data.data(), input_data.size());
}
whole_output[i].emplace_back(std::move(input_data));
}
@@ -418,8 +382,7 @@ WholeOutput RecordMinMax::importH5Data(const std::string &input_data_path)
}
}
-void RecordMinMax::profileData(const std::string &mode, const std::string &input_data_path,
- float min_percentile, float max_percentile)
+void RecordMinMax::profileData(const std::string &input_data_path)
{
try
{
@@ -453,7 +416,8 @@ void RecordMinMax::profileData(const std::string &mode, const std::string &input
{
DataType dtype;
Shape shape;
- importer.readTensor(record_idx, input_idx, &dtype, &shape, input_data.data());
+ importer.readTensor(record_idx, input_idx, &dtype, &shape, input_data.data(),
+ input_data.size());
// Check the type and the shape of the input data is valid
verifyTypeShape(input_node, dtype, shape);
@@ -461,7 +425,7 @@ void RecordMinMax::profileData(const std::string &mode, const std::string &input
else
{
// Skip type/shape check for raw data
- importer.readTensor(record_idx, input_idx, input_data.data());
+ importer.readTensor(record_idx, input_idx, input_data.data(), input_data.size());
}
// TODO: Input data is copied twice (file -> buffer (input_data) -> interpreter inputs)
@@ -480,12 +444,10 @@ void RecordMinMax::profileData(const std::string &mode, const std::string &input
throw std::runtime_error("HDF5 error occurred.");
}
- update_quantparam(getObserver(), mode, min_percentile, max_percentile);
+ _minmax_computer->update_qparam(getObserver()->minMaxData()->getMap());
}
-void RecordMinMax::profileDataInParallel(const std::string &mode,
- const std::string &input_data_path, float min_percentile,
- float max_percentile)
+void RecordMinMax::profileDataInParallel(const std::string &input_data_path)
{
LOGGER(l);
@@ -551,9 +513,8 @@ void RecordMinMax::profileDataInParallel(const std::string &mode,
// End parallel part
- // Copy all min, max values to one observer
- auto observer = std::make_unique<MinMaxObserver>();
- auto main_min_max_map = const_cast<MinMaxMap *>(observer->minMaxData());
+ // Copy all min, max values to one min/max map
+ MinMaxMap main_min_max_map;
for (const auto &obs : _observers)
{
@@ -563,17 +524,16 @@ void RecordMinMax::profileDataInParallel(const std::string &mode,
const auto node = iter.first;
const auto &minmax = iter.second;
- main_min_max_map->appendMinMaxVector(node, minmax);
+ main_min_max_map.appendMinMaxVector(node, minmax);
}
}
std::cout << "Recording finished. Number of recorded data: " << num_records << std::endl;
- update_quantparam(observer.get(), mode, min_percentile, max_percentile);
+ _minmax_computer->update_qparam(main_min_max_map.getMap());
}
-void RecordMinMax::profileDataWithRandomInputs(const std::string &mode, float min_percentile,
- float max_percentile)
+void RecordMinMax::profileDataWithRandomInputs(void)
{
// We use three randomly-generated records
const uint32_t num_records = 3;
@@ -641,7 +601,7 @@ void RecordMinMax::profileDataWithRandomInputs(const std::string &mode, float mi
std::cout << "Recording finished. Number of recorded data: " << num_records << std::endl;
- update_quantparam(getObserver(), mode, min_percentile, max_percentile);
+ _minmax_computer->update_qparam(getObserver()->minMaxData()->getMap());
}
void RecordMinMax::saveModel(const std::string &output_model_path)
diff --git a/compiler/record-minmax/tests/MinMaxComputer.test.cpp b/compiler/record-minmax/tests/MinMaxComputer.test.cpp
new file mode 100644
index 000000000..41babc27d
--- /dev/null
+++ b/compiler/record-minmax/tests/MinMaxComputer.test.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MinMaxComputer.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <unordered_map>
+
+#include <gtest/gtest.h>
+
+using namespace record_minmax;
+
+TEST(MinMaxComputerTest, percentile)
+{
+ auto computer = make_percentile_computer(0.0, 100.0);
+
+ luci::CircleAdd node;
+ MinMaxVectors minmax;
+ {
+ minmax.min_vector = {1.0, 2.0, 3.0};
+ minmax.max_vector = {4.0, 5.0, 6.0};
+ }
+ std::unordered_map<const luci::CircleNode *, MinMaxVectors> min_max_map;
+ min_max_map.insert({&node, minmax});
+
+ computer->update_qparam(&min_max_map);
+
+ EXPECT_TRUE(node.quantparam() != nullptr);
+}
+
+TEST(MinMaxComputerTest, percentile_nullptr_NEG)
+{
+ auto computer = make_percentile_computer(0.0, 100.0);
+
+ EXPECT_ANY_THROW(computer->update_qparam(nullptr));
+}
+
+TEST(MinMaxComputerTest, moving_avg)
+{
+ auto computer = make_moving_avg_computer(1, 0.99);
+
+ luci::CircleAdd node;
+ MinMaxVectors minmax;
+ {
+ minmax.min_vector = {1.0, 2.0, 3.0};
+ minmax.max_vector = {4.0, 5.0, 6.0};
+ }
+ std::unordered_map<const luci::CircleNode *, MinMaxVectors> min_max_map;
+ min_max_map.insert({&node, minmax});
+
+ computer->update_qparam(&min_max_map);
+
+ EXPECT_TRUE(node.quantparam() != nullptr);
+}
+
+TEST(MinMaxComputerTest, moving_avg_nullptr_NEG)
+{
+ auto computer = make_moving_avg_computer(1, 0.99);
+
+ EXPECT_ANY_THROW(computer->update_qparam(nullptr));
+}
diff --git a/compiler/souschef/include/souschef/Data/Gaussian.h b/compiler/souschef/include/souschef/Data/Gaussian.h
index c9ac571f9..801bff8e9 100644
--- a/compiler/souschef/include/souschef/Data/Gaussian.h
+++ b/compiler/souschef/include/souschef/Data/Gaussian.h
@@ -105,6 +105,22 @@ private:
float _stddev;
};
+class GaussianInt8DataChef final : public DataChef
+{
+public:
+ GaussianInt8DataChef(float mean, float stddev) : _mean{mean}, _stddev{stddev}
+ {
+ // DO NOTHING
+ }
+
+public:
+ std::vector<uint8_t> generate(int32_t count) const override;
+
+private:
+ float _mean;
+ float _stddev;
+};
+
struct GaussianFloat32DataChefFactory : public DataChefFactory
{
std::unique_ptr<DataChef> create(const Arguments &args) const;
@@ -130,6 +146,11 @@ struct GaussianFloat16DataChefFactory : public DataChefFactory
std::unique_ptr<DataChef> create(const Arguments &args) const;
};
+struct GaussianInt8DataChefFactory : public DataChefFactory
+{
+ std::unique_ptr<DataChef> create(const Arguments &args) const;
+};
+
} // namespace souschef
#endif // __SOUSCHEF_DATA_GAUSSIAN_H__
diff --git a/compiler/souschef/src/Gaussian.cpp b/compiler/souschef/src/Gaussian.cpp
index a180e24bb..71ab56792 100644
--- a/compiler/souschef/src/Gaussian.cpp
+++ b/compiler/souschef/src/Gaussian.cpp
@@ -115,6 +115,11 @@ std::vector<uint8_t> GaussianUint8DataChef::generate(int32_t count) const
return generate_gaussian<uint8_t>(count, _mean, _stddev);
}
+std::vector<uint8_t> GaussianInt8DataChef::generate(int32_t count) const
+{
+ return generate_gaussian<int8_t>(count, _mean, _stddev);
+}
+
std::unique_ptr<DataChef> GaussianFloat32DataChefFactory::create(const Arguments &args) const
{
if (args.count() != 2)
@@ -167,6 +172,19 @@ std::unique_ptr<DataChef> GaussianUint8DataChefFactory::create(const Arguments &
return std::unique_ptr<DataChef>{new GaussianUint8DataChef{mean, stddev}};
}
+std::unique_ptr<DataChef> GaussianInt8DataChefFactory::create(const Arguments &args) const
+{
+ if (args.count() != 2)
+ {
+ throw std::runtime_error{"invalid argument count: two arguments (mean/stddev) are expected"};
+ }
+
+ auto const mean = to_number<float>(args.value(0));
+ auto const stddev = to_number<float>(args.value(1));
+
+ return std::unique_ptr<DataChef>{new GaussianInt8DataChef{mean, stddev}};
+}
+
std::unique_ptr<DataChef> GaussianFloat16DataChefFactory::create(const Arguments &args) const
{
if (args.count() != 2)
diff --git a/compiler/souschef/src/LexicalCast.cpp b/compiler/souschef/src/LexicalCast.cpp
index 8ab877015..4468f1ec1 100644
--- a/compiler/souschef/src/LexicalCast.cpp
+++ b/compiler/souschef/src/LexicalCast.cpp
@@ -45,6 +45,13 @@ template <> uint8_t to_number(const std::string &s)
assert(temp <= std::numeric_limits<uint8_t>::max());
return static_cast<uint8_t>(temp);
}
+template <> int8_t to_number(const std::string &s)
+{
+ int temp = std::stoi(s);
+ assert(temp >= std::numeric_limits<int8_t>::min());
+ assert(temp <= std::numeric_limits<int8_t>::max());
+ return static_cast<int8_t>(temp);
+}
template <> bool to_number(const std::string &s)
{
if (s == "T" || s == "t" || s == "TRUE" || s == "true" || s == "1")
diff --git a/compiler/tf2tfliteV2-conversion-test/CMakeLists.txt b/compiler/tf2tfliteV2-conversion-test/CMakeLists.txt
index ded416216..017fd6a73 100644
--- a/compiler/tf2tfliteV2-conversion-test/CMakeLists.txt
+++ b/compiler/tf2tfliteV2-conversion-test/CMakeLists.txt
@@ -76,12 +76,7 @@ list(APPEND TEST_DEPS "${TEST_RUNNER}")
get_target_property(ARTIFACTS_BIN_PATH testDataGenerator BINARY_DIR)
-# TODO Run both 2.8.0 and 2.10.1 test for jammy
-if(ONE_UBUNTU_CODENAME_JAMMY)
- set(VIRTUALENV "${NNCC_OVERLAY_DIR}/venv_2_10_1")
-else()
- set(VIRTUALENV "${NNCC_OVERLAY_DIR}/venv_2_8_0")
-endif()
+set(VIRTUALENV "${NNCC_OVERLAY_DIR}/venv_2_12_1")
###
### Generate test.config
diff --git a/compiler/tfl-inspect/CMakeLists.txt b/compiler/tfl-inspect/CMakeLists.txt
index 2c6e3a147..c91ec96e6 100644
--- a/compiler/tfl-inspect/CMakeLists.txt
+++ b/compiler/tfl-inspect/CMakeLists.txt
@@ -1,6 +1,6 @@
-if(NOT TARGET mio_tflite280)
+if(NOT TARGET mio_tflite2121)
return()
-endif(NOT TARGET mio_tflite280)
+endif(NOT TARGET mio_tflite2121)
set(DRIVER "driver/Driver.cpp")
@@ -10,6 +10,6 @@ add_executable(tfl-inspect ${DRIVER} ${SOURCES})
target_include_directories(tfl-inspect PRIVATE src)
target_link_libraries(tfl-inspect arser)
target_link_libraries(tfl-inspect foder)
-target_link_libraries(tfl-inspect mio_tflite280)
-target_link_libraries(tfl-inspect mio_tflite280_helper)
+target_link_libraries(tfl-inspect mio_tflite2121)
+target_link_libraries(tfl-inspect mio_tflite2121_helper)
target_link_libraries(tfl-inspect safemain)
diff --git a/compiler/tfl-inspect/requires.cmake b/compiler/tfl-inspect/requires.cmake
index a11f6b200..80dc592fd 100644
--- a/compiler/tfl-inspect/requires.cmake
+++ b/compiler/tfl-inspect/requires.cmake
@@ -1,4 +1,4 @@
require("arser")
require("foder")
-require("mio-tflite280")
+require("mio-tflite2121")
require("safemain")
diff --git a/compiler/tfl-inspect/src/Reader.cpp b/compiler/tfl-inspect/src/Reader.cpp
index 6c4529516..1ae2e4702 100644
--- a/compiler/tfl-inspect/src/Reader.cpp
+++ b/compiler/tfl-inspect/src/Reader.cpp
@@ -16,7 +16,7 @@
#include "Reader.h"
-#include <mio_tflite280/Helper.h>
+#include <mio_tflite2121/Helper.h>
#include <cassert>
#include <sstream>
diff --git a/compiler/tfl-verify/CMakeLists.txt b/compiler/tfl-verify/CMakeLists.txt
index 5bead5bb4..4e03722d2 100644
--- a/compiler/tfl-verify/CMakeLists.txt
+++ b/compiler/tfl-verify/CMakeLists.txt
@@ -1,6 +1,6 @@
-if(NOT TARGET mio_tflite280)
+if(NOT TARGET mio_tflite2121)
return()
-endif(NOT TARGET mio_tflite280)
+endif(NOT TARGET mio_tflite2121)
file(GLOB_RECURSE SOURCES "src/*.cpp")
@@ -8,6 +8,6 @@ add_executable(tfl-verify ${SOURCES})
target_include_directories(tfl-verify PRIVATE src)
target_link_libraries(tfl-verify arser)
target_link_libraries(tfl-verify foder)
-target_link_libraries(tfl-verify mio_tflite280)
+target_link_libraries(tfl-verify mio_tflite2121)
target_link_libraries(tfl-verify safemain)
target_link_libraries(tfl-verify cwrap)
diff --git a/compiler/tfl-verify/requires.cmake b/compiler/tfl-verify/requires.cmake
index b107bdfe7..9579c2792 100644
--- a/compiler/tfl-verify/requires.cmake
+++ b/compiler/tfl-verify/requires.cmake
@@ -1,5 +1,5 @@
require("arser")
require("foder")
-require("mio-tflite280")
+require("mio-tflite2121")
require("safemain")
require("cwrap")
diff --git a/compiler/tflchef/CMakeLists.txt b/compiler/tflchef/CMakeLists.txt
index 6205ac650..73a8a0d6e 100644
--- a/compiler/tflchef/CMakeLists.txt
+++ b/compiler/tflchef/CMakeLists.txt
@@ -5,10 +5,10 @@ if(NOT Protobuf_FOUND)
return()
endif(NOT Protobuf_FOUND)
-if(NOT TARGET mio_tflite280)
- message(STATUS "Build tflchef: FAILED (missing mio_tflite280)")
+if(NOT TARGET mio_tflite2121)
+ message(STATUS "Build tflchef: FAILED (missing mio_tflite2121)")
return()
-endif(NOT TARGET mio_tflite280)
+endif(NOT TARGET mio_tflite2121)
# Recipe Parser
add_subdirectory(proto)
diff --git a/compiler/tflchef/core/CMakeLists.txt b/compiler/tflchef/core/CMakeLists.txt
index 6b6fed57b..b9f735278 100644
--- a/compiler/tflchef/core/CMakeLists.txt
+++ b/compiler/tflchef/core/CMakeLists.txt
@@ -5,5 +5,5 @@ target_include_directories(tflchef_core PUBLIC include)
target_include_directories(tflchef_core PRIVATE src)
target_link_libraries(tflchef_core tflchef_proto)
target_link_libraries(tflchef_core tflchef_log)
-target_link_libraries(tflchef_core mio_tflite280)
+target_link_libraries(tflchef_core mio_tflite2121)
target_link_libraries(tflchef_core souschef)
diff --git a/compiler/tflchef/core/src/Convert.cpp b/compiler/tflchef/core/src/Convert.cpp
index f4dd4b332..d1babf09a 100644
--- a/compiler/tflchef/core/src/Convert.cpp
+++ b/compiler/tflchef/core/src/Convert.cpp
@@ -77,6 +77,8 @@ tflite::TensorType as_tflite_tensortype(const tflchef::TensorType &value)
return tflite::TensorType_BOOL;
case tflchef::INT16:
return tflite::TensorType_INT16;
+ case tflchef::INT8:
+ return tflite::TensorType_INT8;
default:
break;
}
diff --git a/compiler/tflchef/core/src/CustomOp/Erf.cpp b/compiler/tflchef/core/src/CustomOp/Erf.cpp
new file mode 100644
index 000000000..f611b68e1
--- /dev/null
+++ b/compiler/tflchef/core/src/CustomOp/Erf.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2015 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Erf.h"
+
+#include <flatbuffers/flexbuffers.h>
+
+flatbuffers::Offset<void> ErfChef::value(flatbuffers::FlatBufferBuilder &fbb) const
+{
+ return flatbuffers::Offset<void>();
+}
+
+flatbuffers::Offset<flatbuffers::Vector<uint8_t>>
+ErfChef::custom_value(flatbuffers::FlatBufferBuilder &fbb) const
+{
+ auto &operation = (*_operation);
+
+ assert(operation.type() == "Erf");
+
+ /**
+ * REGISTER_OP("Erf")
+ .Input("x: T")
+ .Output("y: T")
+ .Attr("T: {bfloat16, half, float, double}")
+ .SetShapeFn(shape_inference::UnchangedShape)
+ */
+
+ auto flex_buffers = std::make_unique<flexbuffers::Builder>();
+ size_t map_start = flex_buffers->StartMap();
+
+ // TODO Support more data types
+ flex_buffers->Int("T", tflite::TensorType_FLOAT32);
+
+ flex_buffers->EndMap(map_start);
+ flex_buffers->Finish();
+
+ auto circle_custom_options = fbb.CreateVector(flex_buffers->GetBuffer());
+ return circle_custom_options;
+}
+
+std::unique_ptr<OpChef> ErfChefFactory::create(const tflchef::Operation *operation) const
+{
+ return std::unique_ptr<OpChef>{new ErfChef{operation}};
+}
diff --git a/compiler/tflchef/core/src/CustomOp/Erf.h b/compiler/tflchef/core/src/CustomOp/Erf.h
new file mode 100644
index 000000000..192c5f334
--- /dev/null
+++ b/compiler/tflchef/core/src/CustomOp/Erf.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __OP_ERF_H__
+#define __OP_ERF_H__
+
+#include "OpChef.h"
+
+class ErfChef final : public OpChef
+{
+public:
+ explicit ErfChef(const tflchef::Operation *operation) : _operation{operation}
+ {
+ // DO NOTHING
+ }
+
+public:
+ tflite::BuiltinOperator code(void) const override { return tflite::BuiltinOperator_CUSTOM; }
+
+ tflite::BuiltinOptions type(void) const override { return tflite::BuiltinOptions_NONE; }
+
+ flatbuffers::Offset<void> value(flatbuffers::FlatBufferBuilder &fbb) const override;
+
+ flatbuffers::Offset<flatbuffers::Vector<uint8_t>>
+ custom_value(flatbuffers::FlatBufferBuilder &fbb) const override;
+
+private:
+ const tflchef::Operation *_operation;
+};
+
+struct ErfChefFactory final : public OpChefFactory
+{
+ std::unique_ptr<OpChef> create(const tflchef::Operation *operation) const override;
+};
+
+#endif // __OP_ERF_H__
diff --git a/compiler/tflchef/core/src/DataChef.def b/compiler/tflchef/core/src/DataChef.def
index 28a5b7617..abe642645 100644
--- a/compiler/tflchef/core/src/DataChef.def
+++ b/compiler/tflchef/core/src/DataChef.def
@@ -7,12 +7,14 @@
DATA_CHEF(FLOAT32, constant, ConstantDataChefFactory<float>)
DATA_CHEF(BOOL, constant, ConstantDataChefFactory<bool>)
DATA_CHEF(UINT8, constant, ConstantDataChefFactory<uint8_t>)
+DATA_CHEF(INT8, constant, ConstantDataChefFactory<int8_t>)
DATA_CHEF(INT16, constant, ConstantDataChefFactory<int16_t>)
DATA_CHEF(INT32, constant, ConstantDataChefFactory<int32_t>)
DATA_CHEF(INT64, constant, ConstantDataChefFactory<int64_t>)
DATA_CHEF(INT64, explicit, ExplicitDataChefFactory<int64_t>)
DATA_CHEF(INT32, explicit, ExplicitDataChefFactory<int32_t>)
DATA_CHEF(INT16, explicit, ExplicitDataChefFactory<int16_t>)
+DATA_CHEF(INT8, explicit, ExplicitDataChefFactory<int8_t>)
DATA_CHEF(UINT8, explicit, ExplicitDataChefFactory<uint8_t>)
DATA_CHEF(BOOL, explicit, ExplicitDataChefFactory<bool>)
DATA_CHEF(FLOAT32, explicit, ExplicitDataChefFactory<float>)
@@ -20,6 +22,7 @@ DATA_CHEF(STRING, explicit, ExplicitDataChefFactory<std::string>)
DATA_CHEF(FLOAT32, gaussian, GaussianFloat32DataChefFactory)
DATA_CHEF(INT32, gaussian, GaussianInt32DataChefFactory)
DATA_CHEF(INT16, gaussian, GaussianInt16DataChefFactory)
+DATA_CHEF(INT8, gaussian, GaussianInt8DataChefFactory)
DATA_CHEF(UINT8, gaussian, GaussianUint8DataChefFactory)
// FLOAT16 support for only gaussian, explicit for now
diff --git a/compiler/tflchef/core/src/ModelChef.cpp b/compiler/tflchef/core/src/ModelChef.cpp
index a788adc02..3afcd232d 100644
--- a/compiler/tflchef/core/src/ModelChef.cpp
+++ b/compiler/tflchef/core/src/ModelChef.cpp
@@ -93,6 +93,7 @@ DataChefRegistry &data_chef_registry(const tflchef::TensorType &type)
static DataChefRegistry boolean;
static DataChefRegistry s16;
static DataChefRegistry fp16;
+ static DataChefRegistry s8;
switch (type)
{
@@ -112,6 +113,8 @@ DataChefRegistry &data_chef_registry(const tflchef::TensorType &type)
return boolean;
case tflchef::INT16:
return s16;
+ case tflchef::INT8:
+ return s8;
default:
break;
}
@@ -734,9 +737,19 @@ GeneratedModel cook(const ::tflchef::ModelRecipe &model_recipe)
for (auto const &opcode : builtin_code_map)
{
tflite::OperatorCodeBuilder code_builder{*flatbuffer_builder};
- // TODO support for opcode.first >= 127
- assert(opcode.first < 127);
- code_builder.add_deprecated_builtin_code(opcode.first);
+ // 127 is BuiltinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES
+ // This is the way to handle deprecated builtin code
+ // See
+ // https://github.com/tensorflow/tensorflow/blob/a0afe8f9218be5eb9ed5dffc2dff652996da8c28/tensorflow/lite/schema/schema.fbs#L1061-L1077
+ if (opcode.first < 127)
+ {
+ code_builder.add_deprecated_builtin_code(opcode.first);
+ }
+ else
+ {
+ code_builder.add_deprecated_builtin_code(
+ ::tflite::BuiltinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES);
+ }
code_builder.add_version(opcode.second);
code_builder.add_builtin_code(opcode.first);
auto code = code_builder.Finish();
diff --git a/compiler/tflchef/core/src/Op/Gelu.cpp b/compiler/tflchef/core/src/Op/Gelu.cpp
new file mode 100644
index 000000000..91d2bb36c
--- /dev/null
+++ b/compiler/tflchef/core/src/Op/Gelu.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Gelu.h"
+
+flatbuffers::Offset<void> GeluChef::value(flatbuffers::FlatBufferBuilder &fbb) const
+{
+ assert(_operation->has_gelu_options());
+
+ const auto &options = _operation->gelu_options();
+
+ tflite::GeluOptionsBuilder options_builder{fbb};
+ options_builder.add_approximate(options.approximate());
+
+ return options_builder.Finish().Union();
+}
+
+std::unique_ptr<OpChef> GeluChefFactory::create(const tflchef::Operation *operation) const
+{
+ return std::unique_ptr<OpChef>{new GeluChef{operation}};
+}
diff --git a/compiler/tflchef/core/src/Op/Gelu.h b/compiler/tflchef/core/src/Op/Gelu.h
new file mode 100644
index 000000000..64d9361e6
--- /dev/null
+++ b/compiler/tflchef/core/src/Op/Gelu.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __OP_GELU_H__
+#define __OP_GELU_H__
+
+#include "OpChef.h"
+
+class GeluChef final : public OpChef
+{
+public:
+ explicit GeluChef(const tflchef::Operation *operation) : _operation{operation}
+ {
+ // DO NOTHING
+ }
+
+public:
+ tflite::BuiltinOperator code(void) const override { return tflite::BuiltinOperator_GELU; }
+
+ tflite::BuiltinOptions type(void) const override { return tflite::BuiltinOptions_GeluOptions; }
+
+ flatbuffers::Offset<void> value(flatbuffers::FlatBufferBuilder &fbb) const override;
+
+private:
+ const tflchef::Operation *_operation;
+};
+
+struct GeluChefFactory final : public OpChefFactory
+{
+ std::unique_ptr<OpChef> create(const tflchef::Operation *operation) const override;
+};
+
+#endif // __OP_GELU_H__
diff --git a/compiler/tflchef/core/src/Op/HardSwish.cpp b/compiler/tflchef/core/src/Op/HardSwish.cpp
new file mode 100644
index 000000000..27ab8b5ab
--- /dev/null
+++ b/compiler/tflchef/core/src/Op/HardSwish.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "HardSwish.h"
+
+flatbuffers::Offset<void> HardSwishChef::value(flatbuffers::FlatBufferBuilder &fbb) const
+{
+ return flatbuffers::Offset<void>();
+}
+
+std::unique_ptr<OpChef> HardSwishChefFactory::create(const tflchef::Operation *operation) const
+{
+ return std::unique_ptr<OpChef>{new HardSwishChef{operation}};
+}
diff --git a/compiler/tflchef/core/src/Op/HardSwish.h b/compiler/tflchef/core/src/Op/HardSwish.h
new file mode 100644
index 000000000..10ed51e61
--- /dev/null
+++ b/compiler/tflchef/core/src/Op/HardSwish.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __OP_HARDSWISH_H__
+#define __OP_HARDSWISH_H__
+
+#include "OpChef.h"
+
+class HardSwishChef final : public OpChef
+{
+public:
+ explicit HardSwishChef(const tflchef::Operation *operation) : _operation{operation}
+ {
+ // DO NOTHING
+ }
+
+public:
+ tflite::BuiltinOperator code(void) const override { return tflite::BuiltinOperator_HARD_SWISH; }
+
+ tflite::BuiltinOptions type(void) const override { return tflite::BuiltinOptions_NONE; }
+
+ flatbuffers::Offset<void> value(flatbuffers::FlatBufferBuilder &fbb) const override;
+
+private:
+ const tflchef::Operation *_operation;
+};
+
+struct HardSwishChefFactory final : public OpChefFactory
+{
+ std::unique_ptr<OpChef> create(const tflchef::Operation *operation) const override;
+};
+
+#endif // __OP_HARDSWISH_H__
diff --git a/compiler/tflchef/core/src/Op/TransposeConv.cpp b/compiler/tflchef/core/src/Op/TransposeConv.cpp
index c9e452714..530ebae78 100644
--- a/compiler/tflchef/core/src/Op/TransposeConv.cpp
+++ b/compiler/tflchef/core/src/Op/TransposeConv.cpp
@@ -34,6 +34,13 @@ flatbuffers::Offset<void> TransposeConvChef::value(flatbuffers::FlatBufferBuilde
options_builder.add_stride_h(operation.transpose_conv_options().stride_h());
options_builder.add_stride_w(operation.transpose_conv_options().stride_w());
+ // TODO remove calling has_activation
+ auto chef_activation = operation.transpose_conv_options().has_activation()
+ ? operation.transpose_conv_options().activation()
+ : tflchef::NONE;
+ auto tflite_activation = as_tflite_activation(chef_activation);
+ options_builder.add_fused_activation_function(tflite_activation);
+
return options_builder.Finish().Union();
}
diff --git a/compiler/tflchef/core/src/OpChef.def b/compiler/tflchef/core/src/OpChef.def
index c19d00dfb..9a2164640 100644
--- a/compiler/tflchef/core/src/OpChef.def
+++ b/compiler/tflchef/core/src/OpChef.def
@@ -35,8 +35,10 @@ OP_CHEF(FloorMod, FloorModChefFactory)
OP_CHEF(FullyConnected, FullyConnectedChefFactory)
OP_CHEF(Gather, GatherChefFactory)
OP_CHEF(GatherNd, GatherNdChefFactory)
+OP_CHEF(Gelu, GeluChefFactory)
OP_CHEF(Greater, GreaterChefFactory)
OP_CHEF(GreaterEqual, GreaterEqualChefFactory)
+OP_CHEF(HardSwish, HardSwishChefFactory)
OP_CHEF(If, IfChefFactory)
OP_CHEF(L2Normalize, L2NormalizeChefFactory)
OP_CHEF(L2Pool2D, L2Pool2DChefFactory)
@@ -123,6 +125,7 @@ OP_CHEF(AddV2, AddV2ChefFactory)
OP_CHEF(All, AllChefFactory)
OP_CHEF(BatchMatMulV2, BatchMatMulV2ChefFactory)
OP_CHEF(BroadcastTo, BroadcastToChefFactory)
+OP_CHEF(Erf, ErfChefFactory)
OP_CHEF(MatMul, MatMulChefFactory)
OP_CHEF(MatrixBandPart, MatrixBandPartChefFactory)
OP_CHEF(MaxPoolWithArgmax, MaxPoolWithArgmaxChefFactory)
diff --git a/compiler/tflchef/core/src/OpChefs.h b/compiler/tflchef/core/src/OpChefs.h
index 3cd3be558..ba2b17571 100644
--- a/compiler/tflchef/core/src/OpChefs.h
+++ b/compiler/tflchef/core/src/OpChefs.h
@@ -48,8 +48,10 @@
#include "Op/FullyConnected.h"
#include "Op/Gather.h"
#include "Op/GatherNd.h"
+#include "Op/Gelu.h"
#include "Op/Greater.h"
#include "Op/GreaterEqual.h"
+#include "Op/HardSwish.h"
#include "Op/If.h"
#include "Op/L2Normalize.h"
#include "Op/L2Pool2D.h"
@@ -135,6 +137,7 @@
#include "CustomOp/All.h"
#include "CustomOp/BatchMatMulV2.h"
#include "CustomOp/BroadcastTo.h"
+#include "CustomOp/Erf.h"
#include "CustomOp/MatMul.h"
#include "CustomOp/MatrixBandPart.h"
#include "CustomOp/MaxPoolWithArgmax.h"
diff --git a/compiler/tflchef/proto/tflchef.proto b/compiler/tflchef/proto/tflchef.proto
index da4b6920d..98ae2b23f 100644
--- a/compiler/tflchef/proto/tflchef.proto
+++ b/compiler/tflchef/proto/tflchef.proto
@@ -22,6 +22,7 @@ enum TensorType {
STRING = 5;
BOOL = 6;
INT16 = 7;
+ INT8 = 9;
}
enum DimensionType {
@@ -436,6 +437,10 @@ message GatherNdOptions {
// None
}
+message GeluOptions {
+ optional bool approximate = 1 [default = false];
+}
+
message NonMaxSuppressionV4Options {
// None
}
@@ -473,6 +478,7 @@ message TransposeConvOptions {
optional Padding padding = 1 [default = VALID];
optional int32 stride_w = 2 [default = 1];
optional int32 stride_h = 3 [default = 1];
+ optional Activation activation = 4 [default = NONE];
}
message ReverseSequenceOptions {
@@ -662,6 +668,7 @@ message Operation {
optional MatMulOptions matmul_options = 208;
optional MaxPoolWithArgmaxOptions max_pool_with_argmax_options = 209;
optional DensifyOptions densify_options = 210;
+ optional GeluOptions gelu_options = 211;
// NOTE if there are more than two options with same type of Options
// use the number not listed in the above reserve list
}
diff --git a/compiler/tflchef/requires.cmake b/compiler/tflchef/requires.cmake
index a01da4258..8d86632fb 100644
--- a/compiler/tflchef/requires.cmake
+++ b/compiler/tflchef/requires.cmake
@@ -1,7 +1,7 @@
require("arser")
require("nnkit")
require("cwrap")
-require("mio-tflite280")
+require("mio-tflite2121")
require("safemain")
require("hermes")
require("hermes-std")
diff --git a/compiler/tflchef/tests/CMakeLists.txt b/compiler/tflchef/tests/CMakeLists.txt
index 26cf67f4f..79b00845b 100644
--- a/compiler/tflchef/tests/CMakeLists.txt
+++ b/compiler/tflchef/tests/CMakeLists.txt
@@ -124,9 +124,9 @@ add_custom_target(tflchef_testfiles ALL DEPENDS ${TESTFILES})
# Using mio_tflite_validate for temporary as it only calls flatbuffer validate
# TODO do testing with running the model with runtime/interpreter
-# NOTE for ARM32 cross build, $<TARGET_FILE:mio_tflite280_validate> is used as-is
+# NOTE for ARM32 cross build, $<TARGET_FILE:mio_tflite2121_validate> is used as-is
# as test should run in ARM32 device
add_test(NAME tflchef_test
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/runvalidate.sh"
- $<TARGET_FILE:mio_tflite280_validate>
+ $<TARGET_FILE:mio_tflite2121_validate>
${TESTS})
diff --git a/compiler/tflchef/tests/custom_erf/test.recipe b/compiler/tflchef/tests/custom_erf/test.recipe
new file mode 100644
index 000000000..ab093a30e
--- /dev/null
+++ b/compiler/tflchef/tests/custom_erf/test.recipe
@@ -0,0 +1,17 @@
+operand {
+ name: "ifm"
+ type: FLOAT32
+ shape { dim: 1 dim: 3 dim: 3 dim: 2 }
+}
+operand {
+ name: "ofm"
+ type: FLOAT32
+ shape { dim: 1 dim: 3 dim: 3 dim: 2 }
+}
+operation {
+ type: "Erf"
+ input: "ifm"
+ output: "ofm"
+}
+input: "ifm"
+output: "ofm"
diff --git a/compiler/tflchef/tflite/CMakeLists.txt b/compiler/tflchef/tflite/CMakeLists.txt
index d9a20a2e1..bf20f31c2 100644
--- a/compiler/tflchef/tflite/CMakeLists.txt
+++ b/compiler/tflchef/tflite/CMakeLists.txt
@@ -5,7 +5,7 @@ target_include_directories(tflchef_tflite PUBLIC include)
target_include_directories(tflchef_tflite PRIVATE src)
target_include_directories(tflchef_tflite PRIVATE src/Op/include)
target_link_libraries(tflchef_tflite tflchef_proto)
-target_link_libraries(tflchef_tflite mio_tflite280)
-target_link_libraries(tflchef_tflite mio_tflite280_helper)
+target_link_libraries(tflchef_tflite mio_tflite2121)
+target_link_libraries(tflchef_tflite mio_tflite2121_helper)
target_link_libraries(tflchef_tflite cwrap)
target_link_libraries(tflchef_tflite souschef)
diff --git a/compiler/tflchef/tflite/src/Convert.cpp b/compiler/tflchef/tflite/src/Convert.cpp
index 242987661..46812f4d6 100644
--- a/compiler/tflchef/tflite/src/Convert.cpp
+++ b/compiler/tflchef/tflite/src/Convert.cpp
@@ -33,6 +33,8 @@ tflchef::TensorType as_tflchef_type(const tflite::TensorType type)
return tflchef::UINT8;
case tflite::TensorType_BOOL:
return tflchef::BOOL;
+ case tflite::TensorType_INT8:
+ return tflchef::INT8;
case tflite::TensorType_INT16:
return tflchef::INT16;
case tflite::TensorType_FLOAT16:
diff --git a/compiler/tflchef/tflite/src/Op/Gelu.cpp b/compiler/tflchef/tflite/src/Op/Gelu.cpp
new file mode 100644
index 000000000..23cee07b0
--- /dev/null
+++ b/compiler/tflchef/tflite/src/Op/Gelu.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Gelu.h"
+
+#include "Convert.h"
+
+namespace tflchef
+{
+
+void TFliteOpGelu::filler(const tflite::Operator *op, TFliteImport *import,
+ tflchef::ModelRecipe *model_recipe) const
+{
+ // Nothing to do with filler
+}
+
+tflchef::Operation *TFliteOpGelu::build(const tflite::Operator *op, TFliteImport *import,
+ tflchef::ModelRecipe *model_recipe) const
+{
+ auto op_params = op->builtin_options_as_GeluOptions();
+
+ auto operation = model_recipe->add_operation();
+
+ operation->set_type("Gelu");
+
+ auto *op_options = operation->mutable_gelu_options();
+
+ op_options->set_approximate(op_params->approximate());
+
+ return operation;
+}
+
+} // namespace tflchef
diff --git a/compiler/tflchef/tflite/src/Op/HardSwish.cpp b/compiler/tflchef/tflite/src/Op/HardSwish.cpp
new file mode 100644
index 000000000..2282ff97d
--- /dev/null
+++ b/compiler/tflchef/tflite/src/Op/HardSwish.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "HardSwish.h"
+
+#include "Convert.h"
+
+namespace tflchef
+{
+
+void TFliteOpHardSwish::filler(const tflite::Operator *op, TFliteImport *import,
+ tflchef::ModelRecipe *model_recipe) const
+{
+ // Nothing to do with filler
+}
+
+tflchef::Operation *TFliteOpHardSwish::build(const tflite::Operator *op, TFliteImport *import,
+ tflchef::ModelRecipe *model_recipe) const
+{
+ auto operation = model_recipe->add_operation();
+
+ operation->set_type("HardSwish");
+
+ return operation;
+}
+
+} // namespace tflchef
diff --git a/compiler/tflchef/tflite/src/Op/PRelu.cpp b/compiler/tflchef/tflite/src/Op/PRelu.cpp
index 8a5e83a84..1a1a84bce 100644
--- a/compiler/tflchef/tflite/src/Op/PRelu.cpp
+++ b/compiler/tflchef/tflite/src/Op/PRelu.cpp
@@ -24,6 +24,11 @@ namespace tflchef
void TFliteOpPRelu::filler(const tflite::Operator *op, TFliteImport *import,
tflchef::ModelRecipe *model_recipe) const
{
+ const std::vector<int32_t> &inputs = as_index_vector(op->inputs());
+
+ assert(inputs.size() == 2);
+
+ import->set_tensor_filler(inputs.at(1)); // alpha
}
tflchef::Operation *TFliteOpPRelu::build(const tflite::Operator *op, TFliteImport *import,
diff --git a/compiler/tflchef/tflite/src/Op/TransposeConv.cpp b/compiler/tflchef/tflite/src/Op/TransposeConv.cpp
index 4e7adf6c6..875ccb51b 100644
--- a/compiler/tflchef/tflite/src/Op/TransposeConv.cpp
+++ b/compiler/tflchef/tflite/src/Op/TransposeConv.cpp
@@ -53,10 +53,12 @@ tflchef::Operation *TFliteOpTransposeConv::build(const tflite::Operator *op, TFl
operation->set_type("TransposeConv");
auto op_options = operation->mutable_transpose_conv_options();
+ auto tflchef_activation = as_tflchef_activation(op_params->fused_activation_function());
op_options->set_stride_h(op_params->stride_h());
op_options->set_stride_w(op_params->stride_w());
op_options->set_padding(as_tflchef_padding(op_params->padding()));
+ op_options->set_activation(tflchef_activation);
return operation;
}
diff --git a/compiler/tflchef/tflite/src/Op/include/Gelu.h b/compiler/tflchef/tflite/src/Op/include/Gelu.h
new file mode 100644
index 000000000..0c51a51be
--- /dev/null
+++ b/compiler/tflchef/tflite/src/Op/include/Gelu.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TFLITE_OP_GELU_H__
+#define __TFLITE_OP_GELU_H__
+
+#include "TFliteOpChef.h"
+
+namespace tflchef
+{
+
+/**
+ * @brief tflchef operator builder for Gelu
+ */
+class TFliteOpGelu : public TFliteOpChef
+{
+public:
+ void filler(const tflite::Operator *op, TFliteImport *import,
+ tflchef::ModelRecipe *model_recipe) const override;
+ tflchef::Operation *build(const tflite::Operator *op, TFliteImport *import,
+ tflchef::ModelRecipe *model_recipe) const override;
+};
+
+} // namespace tflchef
+
+#endif // __TFLITE_OP_GELU_H__
diff --git a/compiler/tflchef/tflite/src/Op/include/HardSwish.h b/compiler/tflchef/tflite/src/Op/include/HardSwish.h
new file mode 100644
index 000000000..d9b5a5382
--- /dev/null
+++ b/compiler/tflchef/tflite/src/Op/include/HardSwish.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TFLITE_OP_HARDSWISH_H__
+#define __TFLITE_OP_HARDSWISH_H__
+
+#include "TFliteOpChef.h"
+
+namespace tflchef
+{
+
+/**
+ * @brief tflchef operator builder for Hard Swish
+ */
+class TFliteOpHardSwish : public TFliteOpChef
+{
+public:
+ void filler(const tflite::Operator *op, TFliteImport *import,
+ tflchef::ModelRecipe *model_recipe) const override;
+ tflchef::Operation *build(const tflite::Operator *op, TFliteImport *import,
+ tflchef::ModelRecipe *model_recipe) const override;
+};
+
+} // namespace tflchef
+
+#endif // __TFLITE_OP_HARDSWISH_H__
diff --git a/compiler/tflchef/tflite/src/RecipeChef.cpp b/compiler/tflchef/tflite/src/RecipeChef.cpp
index 0701707c1..2203f5906 100644
--- a/compiler/tflchef/tflite/src/RecipeChef.cpp
+++ b/compiler/tflchef/tflite/src/RecipeChef.cpp
@@ -15,7 +15,7 @@
*/
#include <tflchef/RecipeChef.h>
-#include <mio_tflite280/Helper.h>
+#include <mio_tflite2121/Helper.h>
#include "Convert.h"
#include "TFliteImport.h"
diff --git a/compiler/tflchef/tflite/src/TFliteImport.cpp b/compiler/tflchef/tflite/src/TFliteImport.cpp
index 7114ab019..9abec9a08 100644
--- a/compiler/tflchef/tflite/src/TFliteImport.cpp
+++ b/compiler/tflchef/tflite/src/TFliteImport.cpp
@@ -18,7 +18,7 @@
#include "Convert.h"
-#include <mio_tflite280/Helper.h>
+#include <mio_tflite2121/Helper.h>
#include <sstream>
diff --git a/compiler/tflchef/tflite/src/TFliteOpChefs.h b/compiler/tflchef/tflite/src/TFliteOpChefs.h
index 1b9d420e5..34cb1bae2 100644
--- a/compiler/tflchef/tflite/src/TFliteOpChefs.h
+++ b/compiler/tflchef/tflite/src/TFliteOpChefs.h
@@ -48,8 +48,10 @@
#include "Op/include/FullyConnected.h"
#include "Op/include/Gather.h"
#include "Op/include/GatherNd.h"
+#include "Op/include/Gelu.h"
#include "Op/include/Greater.h"
#include "Op/include/GreaterEqual.h"
+#include "Op/include/HardSwish.h"
#include "Op/include/L2Normalize.h"
#include "Op/include/L2Pool2D.h"
#include "Op/include/LeakyRelu.h"
diff --git a/compiler/tflchef/tflite/src/TFliteOpRegistry.h b/compiler/tflchef/tflite/src/TFliteOpRegistry.h
index 4cbe7cfcb..a37f15c0c 100644
--- a/compiler/tflchef/tflite/src/TFliteOpRegistry.h
+++ b/compiler/tflchef/tflite/src/TFliteOpRegistry.h
@@ -85,8 +85,10 @@ private:
REG_TFL_OP(FULLY_CONNECTED, TFliteOpFullyConnected);
REG_TFL_OP(GATHER, TFliteOpGather);
REG_TFL_OP(GATHER_ND, TFliteOpGatherNd);
+ REG_TFL_OP(GELU, TFliteOpGelu);
REG_TFL_OP(GREATER, TFliteOpGreater);
REG_TFL_OP(GREATER_EQUAL, TFliteOpGreaterEqual);
+ REG_TFL_OP(HARD_SWISH, TFliteOpHardSwish);
REG_TFL_OP(L2_NORMALIZATION, TFliteOpL2Normalize);
REG_TFL_OP(L2_POOL_2D, TFliteOpL2Pool2D);
REG_TFL_OP(LEAKY_RELU, TFliteOpLeakyRelu);
diff --git a/compiler/tfldump/CMakeLists.txt b/compiler/tfldump/CMakeLists.txt
index 410232645..3fe1ea9ac 100644
--- a/compiler/tfldump/CMakeLists.txt
+++ b/compiler/tfldump/CMakeLists.txt
@@ -1,7 +1,7 @@
-if(NOT TARGET mio_tflite280)
- message(STATUS "Build tfldump: FAILED (missing mio_tflite280)")
+if(NOT TARGET mio_tflite2121)
+ message(STATUS "Build tfldump: FAILED (missing mio_tflite2121)")
return()
-endif(NOT TARGET mio_tflite280)
+endif(NOT TARGET mio_tflite2121)
set(DRIVER "driver/Driver.cpp")
@@ -11,6 +11,6 @@ add_executable(tfldump ${DRIVER} ${SOURCES})
target_include_directories(tfldump PRIVATE include)
target_link_libraries(tfldump arser)
target_link_libraries(tfldump foder)
-target_link_libraries(tfldump mio_tflite280)
-target_link_libraries(tfldump mio_tflite280_helper)
+target_link_libraries(tfldump mio_tflite2121)
+target_link_libraries(tfldump mio_tflite2121_helper)
target_link_libraries(tfldump safemain)
diff --git a/compiler/tfldump/requires.cmake b/compiler/tfldump/requires.cmake
index a11f6b200..80dc592fd 100644
--- a/compiler/tfldump/requires.cmake
+++ b/compiler/tfldump/requires.cmake
@@ -1,4 +1,4 @@
require("arser")
require("foder")
-require("mio-tflite280")
+require("mio-tflite2121")
require("safemain")
diff --git a/compiler/tfldump/src/Dump.cpp b/compiler/tfldump/src/Dump.cpp
index 4388fcde8..a3450396b 100644
--- a/compiler/tfldump/src/Dump.cpp
+++ b/compiler/tfldump/src/Dump.cpp
@@ -15,7 +15,7 @@
*/
#include <tfldump/Dump.h>
-#include <mio_tflite280/Helper.h>
+#include <mio_tflite2121/Helper.h>
#include "Read.h"
#include "OpPrinter.h"
diff --git a/compiler/tfldump/src/OpPrinter.cpp b/compiler/tfldump/src/OpPrinter.cpp
index 2e8e7134f..f8777fad9 100644
--- a/compiler/tfldump/src/OpPrinter.cpp
+++ b/compiler/tfldump/src/OpPrinter.cpp
@@ -359,6 +359,19 @@ public:
}
};
+class GeluPrinter : public OpPrinter
+{
+public:
+ void options(const tflite::Operator *op, std::ostream &os) const override
+ {
+ if (auto *params = op->builtin_options_as_GeluOptions())
+ {
+ os << " ";
+ os << "approximate(" << params->approximate() << ") ";
+ }
+ }
+};
+
class IfPrinter : public OpPrinter
{
public:
@@ -630,6 +643,8 @@ public:
os << "Padding(" << params->padding() << ") ";
os << "Stride.W(" << params->stride_w() << ") ";
os << "Stride.H(" << params->stride_h() << ") ";
+ os << "Activation(" << EnumNameActivationFunctionType(params->fused_activation_function())
+ << ") ";
os << std::endl;
}
}
@@ -746,6 +761,7 @@ OpPrinterRegistry::OpPrinterRegistry()
// There is no Option for FLOOR_MOD
_op_map[tflite::BuiltinOperator_FULLY_CONNECTED] = make_unique<FullyConnectedPrinter>();
_op_map[tflite::BuiltinOperator_GATHER] = make_unique<GatherPrinter>();
+ _op_map[tflite::BuiltinOperator_GELU] = make_unique<GeluPrinter>();
_op_map[tflite::BuiltinOperator_IF] = make_unique<IfPrinter>();
_op_map[tflite::BuiltinOperator_L2_POOL_2D] = make_unique<Pool2DPrinter>();
_op_map[tflite::BuiltinOperator_L2_NORMALIZATION] = make_unique<L2NormPrinter>();
diff --git a/compiler/tfldump/src/Read.cpp b/compiler/tfldump/src/Read.cpp
index 454e3a8a1..7fa3d8181 100644
--- a/compiler/tfldump/src/Read.cpp
+++ b/compiler/tfldump/src/Read.cpp
@@ -16,7 +16,7 @@
#include "Read.h"
-#include <mio_tflite280/Helper.h>
+#include <mio_tflite2121/Helper.h>
#include <sstream>
#include <string>
diff --git a/compiler/tflite2circle/CMakeLists.txt b/compiler/tflite2circle/CMakeLists.txt
index a317a6305..73639f390 100644
--- a/compiler/tflite2circle/CMakeLists.txt
+++ b/compiler/tflite2circle/CMakeLists.txt
@@ -1,8 +1,8 @@
nnas_include(TargetRequire)
unset(REQUIRED_TARGETS)
-list(APPEND REQUIRED_TARGETS mio_tflite280)
-list(APPEND REQUIRED_TARGETS mio_circle04)
+list(APPEND REQUIRED_TARGETS mio_tflite2121)
+list(APPEND REQUIRED_TARGETS mio_circle06)
TargetRequire_Return(${REQUIRED_TARGETS})
set(DRIVER "driver/Driver.cpp")
@@ -13,9 +13,9 @@ target_include_directories(tflite2circle PRIVATE src)
target_link_libraries(tflite2circle arser)
target_link_libraries(tflite2circle foder)
target_link_libraries(tflite2circle safemain)
-target_link_libraries(tflite2circle mio_tflite280)
-target_link_libraries(tflite2circle mio_tflite280_helper)
-target_link_libraries(tflite2circle mio_circle04)
+target_link_libraries(tflite2circle mio_tflite2121)
+target_link_libraries(tflite2circle mio_tflite2121_helper)
+target_link_libraries(tflite2circle mio_circle06)
target_link_libraries(tflite2circle vconone)
target_link_libraries(tflite2circle nncc_coverage)
diff --git a/compiler/tflite2circle/requires.cmake b/compiler/tflite2circle/requires.cmake
index 3db9a2f2a..c5528c28a 100644
--- a/compiler/tflite2circle/requires.cmake
+++ b/compiler/tflite2circle/requires.cmake
@@ -1,6 +1,6 @@
require("arser")
require("foder")
-require("mio-tflite280")
-require("mio-circle04")
+require("mio-tflite2121")
+require("mio-circle06")
require("safemain")
require("vconone")
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions.h b/compiler/tflite2circle/src/BuildBuiltinOptions.h
index 8149197f6..5ed88ce02 100644
--- a/compiler/tflite2circle/src/BuildBuiltinOptions.h
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions.h
@@ -46,6 +46,7 @@
#include "BuildBuiltinOptions/FullyConnectedOptions.h"
#include "BuildBuiltinOptions/GatherOptions.h"
#include "BuildBuiltinOptions/GatherNdOptions.h"
+#include "BuildBuiltinOptions/GeluOptions.h"
#include "BuildBuiltinOptions/GreaterOptions.h"
#include "BuildBuiltinOptions/GreaterEqualOptions.h"
#include "BuildBuiltinOptions/IfOptions.h"
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/GeluOptions.cpp b/compiler/tflite2circle/src/BuildBuiltinOptions/GeluOptions.cpp
new file mode 100644
index 000000000..92fcd6083
--- /dev/null
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/GeluOptions.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GeluOptions.h"
+
+namespace tflite2circle
+{
+
+flatbuffers::Offset<circle::GeluOptions>
+build_circle_GeluOptions(flatbuffers::FlatBufferBuilder &fb, const tflite::Operator *op)
+{
+ auto *tflite_builtin_options = op->builtin_options_as_GeluOptions();
+ assert(tflite_builtin_options);
+ circle::GeluOptionsBuilder builtin_options_builder{fb};
+ builtin_options_builder.add_approximate(tflite_builtin_options->approximate());
+ return builtin_options_builder.Finish();
+}
+
+} // namespace tflite2circle
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/GeluOptions.h b/compiler/tflite2circle/src/BuildBuiltinOptions/GeluOptions.h
new file mode 100644
index 000000000..76955d795
--- /dev/null
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/GeluOptions.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __BBO_GELU_OPTIONS_H__
+#define __BBO_GELU_OPTIONS_H__
+
+#include <mio/tflite/schema_generated.h>
+#include <mio/circle/schema_generated.h>
+
+namespace tflite2circle
+{
+
+flatbuffers::Offset<circle::GeluOptions>
+build_circle_GeluOptions(flatbuffers::FlatBufferBuilder &fb, const tflite::Operator *op);
+
+} // namespace tflite2circle
+
+#endif // __BBO_GELU_OPTIONS_H__
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/TransposeConvOptions.cpp b/compiler/tflite2circle/src/BuildBuiltinOptions/TransposeConvOptions.cpp
index 301f2c421..0873170f7 100644
--- a/compiler/tflite2circle/src/BuildBuiltinOptions/TransposeConvOptions.cpp
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/TransposeConvOptions.cpp
@@ -31,6 +31,8 @@ build_circle_TransposeConvOptions(flatbuffers::FlatBufferBuilder &fb, const tfli
builtin_options_builder.add_padding(get_circle_padding(tflite_builtin_options->padding()));
builtin_options_builder.add_stride_w(tflite_builtin_options->stride_w());
builtin_options_builder.add_stride_h(tflite_builtin_options->stride_h());
+ builtin_options_builder.add_fused_activation_function(
+ get_circle_activation_function_type(tflite_builtin_options->fused_activation_function()));
return builtin_options_builder.Finish();
}
diff --git a/compiler/tflite2circle/src/CircleModel.cpp b/compiler/tflite2circle/src/CircleModel.cpp
index ac017b8f1..899bc84f7 100644
--- a/compiler/tflite2circle/src/CircleModel.cpp
+++ b/compiler/tflite2circle/src/CircleModel.cpp
@@ -22,7 +22,7 @@
#include "CircleModel.h"
#include "DataLookup.h"
-#include <mio_tflite280/Helper.h>
+#include <mio_tflite2121/Helper.h>
namespace tflite2circle
{
@@ -344,13 +344,31 @@ template <> void Offset<OperatorCodeLink>::build(const TFLFlatBufVec *tflite_fla
circle::OperatorCodeBuilder operator_code_builder{*_fb};
auto de_code = it->deprecated_builtin_code();
auto bt_code = it->builtin_code();
- auto cir_de_code = get_circle_builtin_code(de_code);
- auto cir_bt_code = get_circle_builtin_code(bt_code);
- // correct bt_code where bt_code == 0 for old tflite format
- if (cir_bt_code == 0)
- cir_bt_code = static_cast<circle::BuiltinOperator>(cir_de_code);
- operator_code_builder.add_deprecated_builtin_code(cir_de_code);
- operator_code_builder.add_builtin_code(cir_bt_code);
+
+ // There are two builtin codes (deprecated_builtin, (extended) builtin)
+ // deprecated builtin code uses 0~126
+ // extended builtin code uses 127~
+ // NOTE 127 = BuiltinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES
+ if (de_code >= 0 and de_code < 127)
+ {
+ // Use deprecated builtin opcode.
+ auto cir_de_code = get_circle_builtin_code(de_code);
+ auto cir_bt_code = get_circle_builtin_code(bt_code);
+ // correct bt_code where bt_code == 0 for old tflite format
+ if (cir_bt_code == 0)
+ cir_bt_code = static_cast<circle::BuiltinOperator>(cir_de_code);
+ operator_code_builder.add_deprecated_builtin_code(cir_de_code);
+ operator_code_builder.add_builtin_code(cir_bt_code);
+ }
+ else
+ {
+ // Use extended builtin opcode
+ // Set 127 (PLACEHOLDER_FOR_GREATER_OP_CODES) for deprecated builtin code
+ auto cir_bt_code = get_circle_builtin_code(bt_code);
+ operator_code_builder.add_deprecated_builtin_code(
+ tflite::BuiltinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES);
+ operator_code_builder.add_builtin_code(cir_bt_code);
+ }
operator_code_builder.add_custom_code(custom_code);
operator_code_builder.add_version(it->version());
auto code = operator_code_builder.Finish();
diff --git a/compiler/tflite2circle/src/TFLBuiltinOptions.lst b/compiler/tflite2circle/src/TFLBuiltinOptions.lst
index 9cbf8032a..ac77c9abf 100644
--- a/compiler/tflite2circle/src/TFLBuiltinOptions.lst
+++ b/compiler/tflite2circle/src/TFLBuiltinOptions.lst
@@ -28,6 +28,7 @@ TFL_BUILTIN_OPTIONS(MulOptions)
TFL_BUILTIN_OPTIONS(PadOptions)
TFL_BUILTIN_OPTIONS(PadV2Options)
TFL_BUILTIN_OPTIONS(GatherOptions)
+TFL_BUILTIN_OPTIONS(GeluOptions)
TFL_BUILTIN_OPTIONS(BatchToSpaceNDOptions)
TFL_BUILTIN_OPTIONS(SpaceToBatchNDOptions)
TFL_BUILTIN_OPTIONS(TransposeOptions)
diff --git a/compiler/tflite2circle/src/TFLOperator.lst b/compiler/tflite2circle/src/TFLOperator.lst
index 72a29fce5..b7db49b0a 100644
--- a/compiler/tflite2circle/src/TFLOperator.lst
+++ b/compiler/tflite2circle/src/TFLOperator.lst
@@ -151,3 +151,4 @@ TFL_OPERATOR(READ_VARIABLE)
TFL_OPERATOR(ASSIGN_VARIABLE)
TFL_OPERATOR(BROADCAST_ARGS)
TFL_OPERATOR(RANDOM_STANDARD_NORMAL)
+TFL_OPERATOR(GELU)
diff --git a/compiler/vconone/CMakeLists.txt b/compiler/vconone/CMakeLists.txt
index 38e868685..c5c9be25f 100644
--- a/compiler/vconone/CMakeLists.txt
+++ b/compiler/vconone/CMakeLists.txt
@@ -1,5 +1,5 @@
if (NOT VCONONE_VERSION)
- set(VCONONE_VERSION 0x0000000000160001)
+ set(VCONONE_VERSION 0x0000000000190001)
# NOTE order is [build patch minor major]
# if VCONONE_VERSION is set with -D option, it will be cached
# you may have to remove cache file if you remove -D option
diff --git a/compiler/vconone/src/version.cpp b/compiler/vconone/src/version.cpp
index cebf7d998..fd34e9204 100644
--- a/compiler/vconone/src/version.cpp
+++ b/compiler/vconone/src/version.cpp
@@ -54,7 +54,7 @@ std::string get_string(void)
std::string get_copyright(void)
{
std::string str;
- str = "Copyright (c) 2020-2022 Samsung Electronics Co., Ltd. All Rights Reserved\r\n";
+ str = "Copyright (c) 2020-2023 Samsung Electronics Co., Ltd. All Rights Reserved\r\n";
str += "Licensed under the Apache License, Version 2.0\r\n";
str += "https://github.com/Samsung/ONE";
return str;
diff --git a/compiler/visq-unittest/CMakeLists.txt b/compiler/visq-unittest/CMakeLists.txt
index 4eefa8dfd..7cc0bc040 100644
--- a/compiler/visq-unittest/CMakeLists.txt
+++ b/compiler/visq-unittest/CMakeLists.txt
@@ -53,14 +53,6 @@ add_custom_target(visq_unittest ALL DEPENDS ${VISQ_TEST_DEPS})
# Use Python in venv to run unittest with pydot module
add_test(
NAME visq_unittest
- COMMAND ${NNCC_OVERLAY_DIR}/venv_2_8_0/bin/python -m unittest
+ COMMAND ${NNCC_OVERLAY_DIR}/venv_2_12_1/bin/python -m unittest
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
-
-if(ONE_UBUNTU_CODENAME_JAMMY)
- add_test(
- NAME visq_210_unittest
- COMMAND ${NNCC_OVERLAY_DIR}/venv_2_10_1/bin/python -m unittest
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- )
-endif(ONE_UBUNTU_CODENAME_JAMMY)
diff --git a/compiler/visq-unittest/test/testDotBuilder.py b/compiler/visq-unittest/test/testDotBuilder.py
index b657d60c5..d0e6adaae 100644
--- a/compiler/visq-unittest/test/testDotBuilder.py
+++ b/compiler/visq-unittest/test/testDotBuilder.py
@@ -15,7 +15,6 @@
import unittest
import pydot
-from pathlib import Path
from visqlib.DotBuilder import DotBuilder
from test.Resources import fp32_model_dir
diff --git a/compiler/visq-unittest/test/testQErrorComputer.py b/compiler/visq-unittest/test/testQErrorComputer.py
index 1c6b18556..3065b7171 100644
--- a/compiler/visq-unittest/test/testQErrorComputer.py
+++ b/compiler/visq-unittest/test/testQErrorComputer.py
@@ -17,10 +17,12 @@ import unittest
import tempfile
import numpy as np
import os
+import json
from visqlib.QErrorComputer import MPEIRComputer
from visqlib.QErrorComputer import MSEComputer
from visqlib.QErrorComputer import TAEComputer
+from visqlib.QErrorComputer import SRMSEComputer
class VisqQErrorComputerTest(unittest.TestCase):
@@ -35,31 +37,43 @@ class VisqQErrorComputerTest(unittest.TestCase):
self.fq_dir.cleanup()
def _setUpSingleTensorData(self):
- with open(self.fp32_dir.name + '/tensors.txt', 'w') as f:
- f.write('test')
- with open(self.fq_dir.name + '/tensors.txt', 'w') as f:
- f.write('test')
+ tensor_id = {}
+ tensor_id['test'] = 0
+ with open(self.fp32_dir.name + '/tensors.json', 'w') as f:
+ json.dump(tensor_id, f)
+ with open(self.fq_dir.name + '/tensors.json', 'w') as f:
+ json.dump(tensor_id, f)
+ scales = {}
+ scales['test'] = 2.0
+ with open(self.fq_dir.name + '/scales.txt', 'w') as f:
+ json.dump(scales, f)
os.mkdir(self.fp32_dir.name + '/0')
os.mkdir(self.fq_dir.name + '/0')
test_data = np.zeros(16)
- np.save(self.fp32_dir.name + '/0/test.npy', test_data)
- np.save(self.fq_dir.name + '/0/test.npy', test_data)
+ np.save(self.fp32_dir.name + '/0/0.npy', test_data)
+ np.save(self.fq_dir.name + '/0/0.npy', test_data)
def _setUpTwoTensorData(self):
- with open(self.fp32_dir.name + '/tensors.txt', 'w') as f:
- f.write('test')
- with open(self.fq_dir.name + '/tensors.txt', 'w') as f:
- f.write('test')
+ tensor_id = {}
+ tensor_id['test'] = 0
+ with open(self.fp32_dir.name + '/tensors.json', 'w') as f:
+ json.dump(tensor_id, f)
+ with open(self.fq_dir.name + '/tensors.json', 'w') as f:
+ json.dump(tensor_id, f)
+ scales = {}
+ scales['test'] = 2.0
+ with open(self.fq_dir.name + '/scales.txt', 'w') as f:
+ json.dump(scales, f)
os.mkdir(self.fp32_dir.name + '/0')
os.mkdir(self.fp32_dir.name + '/1')
os.mkdir(self.fq_dir.name + '/0')
os.mkdir(self.fq_dir.name + '/1')
test_data_one = np.ones(16)
test_data_zero = np.zeros(16)
- np.save(self.fp32_dir.name + '/0/test.npy', test_data_one)
- np.save(self.fp32_dir.name + '/1/test.npy', test_data_zero)
- np.save(self.fq_dir.name + '/0/test.npy', test_data_zero)
- np.save(self.fq_dir.name + '/1/test.npy', test_data_zero)
+ np.save(self.fp32_dir.name + '/0/0.npy', test_data_one)
+ np.save(self.fp32_dir.name + '/1/0.npy', test_data_zero)
+ np.save(self.fq_dir.name + '/0/0.npy', test_data_zero)
+ np.save(self.fq_dir.name + '/1/0.npy', test_data_zero)
# Golden: (1 + 0) / 2 = 0.5 for MSE
def _setUpDifferentTensorData(self):
@@ -68,30 +82,38 @@ class VisqQErrorComputerTest(unittest.TestCase):
# NOTE When does this happen?
# This case can happen because visq ignores nodes that do not affect qerrors.
# For example, RESHAPE Op does not affect qerrors, so its fq data is not dumped,
- # although it is listed in 'tensors.txt'.
- with open(self.fp32_dir.name + '/tensors.txt', 'w') as f:
- f.writelines(['test\n', 'test2'])
- with open(self.fq_dir.name + '/tensors.txt', 'w') as f:
- f.writelines(['test\n', 'test2'])
+ # although it is listed in 'tensors.json'.
+ tensor_id = {}
+ tensor_id['test'] = 0
+ tensor_id['test2'] = 1
+ with open(self.fp32_dir.name + '/tensors.json', 'w') as f:
+ json.dump(tensor_id, f)
+ with open(self.fq_dir.name + '/tensors.json', 'w') as f:
+ json.dump(tensor_id, f)
+ scales = {}
+ scales['test'] = 2.0
+ scales['test2'] = 1.0
+ with open(self.fq_dir.name + '/scales.txt', 'w') as f:
+ json.dump(scales, f)
os.mkdir(self.fp32_dir.name + '/0')
os.mkdir(self.fq_dir.name + '/0')
test_data = np.zeros(16)
- np.save(self.fp32_dir.name + '/0/test.npy', test_data)
- np.save(self.fp32_dir.name + '/0/test2.npy', test_data)
- np.save(self.fq_dir.name + '/0/test.npy', test_data)
+ np.save(self.fp32_dir.name + '/0/0.npy', test_data)
+ np.save(self.fp32_dir.name + '/0/1.npy', test_data)
+ np.save(self.fq_dir.name + '/0/0.npy', test_data)
def test_MPEIR(self):
self._setUpSingleTensorData()
computer = MPEIRComputer(self.fp32_dir.name, self.fq_dir.name)
- qmap = computer.run()
+ qmap, _, _ = computer.run()
self.assertAlmostEqual(0.0, qmap['test'])
def test_MPEIR_different_tensors(self):
self._setUpDifferentTensorData()
computer = MPEIRComputer(self.fp32_dir.name, self.fq_dir.name)
- qmap = computer.run()
+ qmap, _, _ = computer.run()
self.assertAlmostEqual(0.0, qmap['test'])
def test_MSE(self):
@@ -145,6 +167,33 @@ class VisqQErrorComputerTest(unittest.TestCase):
self.assertAlmostEqual(8.0, qmap['test'])
self.assertAlmostEqual(16.0, qmax)
+ def test_SRMSE(self):
+ self._setUpSingleTensorData()
+
+ computer = SRMSEComputer(self.fp32_dir.name, self.fq_dir.name)
+ qmap, qmin, qmax = computer.run()
+ self.assertAlmostEqual(0.0, qmap['test'])
+ self.assertAlmostEqual(0.0, qmin)
+ self.assertAlmostEqual(0.0, qmax)
+
+ def test_SRMSE_different_options(self):
+ self._setUpDifferentTensorData()
+
+ computer = SRMSEComputer(self.fp32_dir.name, self.fq_dir.name)
+ qmap, qmin, qmax = computer.run()
+ self.assertAlmostEqual(0.0, qmap['test'])
+ self.assertAlmostEqual(0.0, qmin)
+ self.assertAlmostEqual(0.0, qmax)
+
+ def test_SRMSE_two(self):
+ self._setUpTwoTensorData()
+ computer = SRMSEComputer(self.fp32_dir.name, self.fq_dir.name)
+ qmap, qmin, qmax = computer.run()
+ # Golden: sqrt(Golden of MSE) / scale = sqrt(0.5) / 2
+ self.assertAlmostEqual(np.sqrt(0.5) / 2, qmap['test'])
+ self.assertAlmostEqual(0.0, qmin)
+ self.assertAlmostEqual(np.sqrt(0.5) / 2, qmax)
+
if __name__ == '__main__':
unittest.main()
diff --git a/compiler/visq/CMakeLists.txt b/compiler/visq/CMakeLists.txt
index 0dd1b78e5..6d13a7eca 100644
--- a/compiler/visq/CMakeLists.txt
+++ b/compiler/visq/CMakeLists.txt
@@ -44,7 +44,7 @@ foreach(VISQ_PYTHON_FILE IN ITEMS ${VISQ_PYTHON_FILES})
add_custom_command(OUTPUT ${VISQ_PYTHON_FILE_BIN}
COMMAND ${CMAKE_COMMAND} -E copy "${VISQ_PYTHON_FILE_SRC}" "${VISQ_PYTHON_FILE_BIN}"
- DEPENDS ${VISQ_PYTHON_SRC}
+ DEPENDS ${VISQ_PYTHON_FILE_SRC}
COMMENT "Generate ${VISQ_PYTHON_FILE_BIN}"
)
diff --git a/compiler/visq/visq b/compiler/visq/visq
index 02f63abed..6c3b94d11 100644
--- a/compiler/visq/visq
+++ b/compiler/visq/visq
@@ -34,7 +34,7 @@ from shutil import copyfile
from pathlib import Path
from visqlib.Palette import YLORRD9Palette
-from visqlib.QErrorComputer import MPEIRComputer, MSEComputer, TAEComputer
+from visqlib.QErrorComputer import MPEIRComputer, MSEComputer, TAEComputer, SRMSEComputer
from visqlib.Util import valid_attr, pretty_float
from visqlib.DotBuilder import DotBuilder
@@ -77,6 +77,11 @@ def _get_parser():
help="Path to the output json file (qerror metric = TAE).",
required=False)
parser.add_argument(
+ "--srmse_output",
+ type=str,
+ help="Path to the output json file (qerror metric = SRMSE).",
+ required=False)
+ parser.add_argument(
"--dump_dot_graph", action="store_true", help="Dump dot graph.", required=False)
parser.add_argument(
"-b",
@@ -91,7 +96,7 @@ def _get_parser():
def _verify_args(args):
"""Verify the given arguments"""
- valid_outputs = ['mpeir_output', 'mse_output', 'tae_output']
+ valid_outputs = ['mpeir_output', 'mse_output', 'tae_output', 'srmse_output']
# Check if at least one output option is given
num_outputs = 0
@@ -114,22 +119,24 @@ def _run_dalgona(model, data, analysis, save_dir):
cmd += ['--analysis_args', str(save_dir)]
try:
- subprocess.run(cmd, capture_output=True, check=True)
+ subprocess.run(cmd, capture_output=True, check=True, universal_newlines=True)
except subprocess.CalledProcessError as e:
print('Error raised while running the below command')
print(' '.join(cmd))
- print(e.output)
+ print(e.stderr)
raise
# Generate h5 file that contains a dataset of a single batch
# This is for batch execution of visq
-def gen_batch_h5(inputs_data, inputs_path):
+def gen_batch_h5(inputs_data, inputs_path, rawData):
# Create h5 file
output_path = inputs_path + "/inputs.h5"
h5_file = h5.File(output_path, 'w')
group = h5_file.create_group("value")
group.attrs['desc'] = "Input data"
+ if rawData:
+ group.attrs['rawData'] = '1'
for i in range(len(inputs_data)):
sample = group.create_group(str(i))
@@ -151,7 +158,7 @@ def advance_on_data(fp32_model, fq_model, data, computers):
tempfile.TemporaryDirectory() as fq_dir:
_run_dalgona(fp32_model, data, dump_fp32_py, fp32_dir)
- copyfile(fp32_dir + '/tensors.txt', fq_dir + '/tensors.txt')
+ copyfile(fp32_dir + '/tensors.json', fq_dir + '/tensors.json')
_run_dalgona(fq_model, data, dump_fq_py, fq_dir)
for metric_key in computers:
@@ -162,22 +169,23 @@ def _run_batch(fp32_model, fq_model, data, computers, batch_size):
with tempfile.TemporaryDirectory() as inputs_dir:
with h5.File(data, 'r') as f:
dataset = f['value']
-
+ rawData = dataset.attrs.__contains__(
+ 'rawData') and dataset.attrs['rawData'] == '1'
inputs = []
for data_index in dataset:
cur_inputs = []
for input_index in dataset[data_index]:
d = dataset[data_index][input_index][:]
- cur_inputs.append(np.array(d, np.float32))
+ cur_inputs.append(d)
inputs.append(cur_inputs)
if len(inputs) >= batch_size:
- input_path = gen_batch_h5(inputs, inputs_dir)
+ input_path = gen_batch_h5(inputs, inputs_dir, rawData)
advance_on_data(fp32_model, fq_model, input_path, computers)
inputs = []
if len(inputs) > 0:
- input_path = gen_batch_h5(inputs, inputs_dir)
+ input_path = gen_batch_h5(inputs, inputs_dir, rawData)
advance_on_data(fp32_model, fq_model, input_path, computers)
@@ -190,11 +198,11 @@ def _fake_quantize(input_model, output_model):
cmd += [str(output_model)]
try:
- subprocess.run(cmd, check=True)
+ subprocess.run(cmd, check=True, universal_newlines=True)
except subprocess.CalledProcessError as e:
print('Error raised while running the below command')
print(' '.join(cmd))
- print(e.output)
+ print(e.stderr)
raise
@@ -262,12 +270,7 @@ def run_on_data_batchwise(fp32_model, q_model, data, dump_dot_graph, computers,
for metric_key in computers:
cur_computer = computers[metric_key][0]
output = computers[metric_key][1]
- if metric_key == 'MPEIR':
- qerror_map = cur_computer.get_final_result()
- q_min = 0.0
- q_max = 1.0
- elif metric_key == 'MSE' or metric_key == 'TAE':
- qerror_map, q_min, q_max = cur_computer.get_final_result()
+ qerror_map, q_min, q_max = cur_computer.get_final_result()
palette = YLORRD9Palette(qerror_min=q_min, qerror_max=q_max)
result = _build_json(
@@ -304,7 +307,7 @@ def run_on_data(fp32_model, q_model, data, dump_dot_graph, computers):
_run_dalgona(fp32_model, data, dump_fp32_py, fp32_dir)
# Copy list of dumped tensors
- copyfile(fp32_dir + '/tensors.txt', fq_dir + '/tensors.txt')
+ copyfile(fp32_dir + '/tensors.json', fq_dir + '/tensors.json')
# Step 3. Run dalgona to dump intermediate FMs in fq model
_run_dalgona(fq_model, data, dump_fq_py, fq_dir)
@@ -314,12 +317,7 @@ def run_on_data(fp32_model, q_model, data, dump_dot_graph, computers):
cur_computer = computers[metric_key][0]
output = computers[metric_key][1]
cur_computer.advance_on(fp32_dir, fq_dir)
- if metric_key == 'MPEIR':
- qerror_map = cur_computer.get_final_result()
- q_min = 0.0
- q_max = 1.0
- elif metric_key == 'MSE' or metric_key == 'TAE':
- qerror_map, q_min, q_max = cur_computer.get_final_result()
+ qerror_map, q_min, q_max = cur_computer.get_final_result()
palette = YLORRD9Palette(qerror_min=q_min, qerror_max=q_max)
result = _build_json(
@@ -365,6 +363,9 @@ def main():
if args.tae_output:
computers['TAE'] = (TAEComputer(None, None), args.tae_output)
+ if args.srmse_output:
+ computers['SRMSE'] = (SRMSEComputer(None, None), args.srmse_output)
+
if batch_size == None:
run_on_data(fp32_model, q_model, data, dump_dot_graph, computers)
else:
diff --git a/compiler/visq/visqlib/DumpFP32FM.py b/compiler/visq/visqlib/DumpFP32FM.py
index d5b754559..14dc900c5 100644
--- a/compiler/visq/visqlib/DumpFP32FM.py
+++ b/compiler/visq/visqlib/DumpFP32FM.py
@@ -16,9 +16,9 @@
# NOTE This script runs on dalgona
import numpy as np
+import json
from pathlib import Path
-from Util import to_filename
# Dump FP32 model's intermediate FM data and their names
@@ -28,27 +28,37 @@ from Util import to_filename
#
# After
# self._dir/
-# tensors.txt
-# <TENSOR_NAME>.npy
-# NOTE TENSOR_NAME is transformed by to_filename
+# tensors.json
+# <TENSOR_ID>.npy
+# NOTE tensors.json has a dictionary {TENSOR_NAME -> TENSOR_ID}
class DumpFP32FM:
def StartAnalysis(self, args):
self._dir = Path(args)
self._num_data = 0
- self._tensor_names = set()
+ # Dict {tensor_name -> tid}
+ self._tname_to_tid = dict()
+ self._tensor_count = 0
def EndNetworkExecution(self, outputs):
self._num_data += 1
- def DefaultOpPost(self, name, opcode, inputs, output):
- # Save intermediate FM into tensor_name.npy
+ def DefaultOpPost(self, name, opcode, inputs, outputs):
+ # Save intermediate FM into <tid>.npy
data_path = self._dir / str(self._num_data)
data_path.mkdir(parents=False, exist_ok=True)
- np.save(str(data_path / to_filename(name)), output['data'])
- self._tensor_names.add(name)
+ for output in outputs:
+ name = output['name']
+ data = output['data']
+ if name in self._tname_to_tid:
+ tid = self._tname_to_tid[name]
+ else:
+ tid = self._tensor_count
+ self._tname_to_tid[name] = tid
+ self._tensor_count += 1
+
+ np.save(str(data_path / str(tid)), data)
def EndAnalysis(self):
- # Save tensor names line by line
- with open(self._dir / 'tensors.txt', 'w') as f:
- for name in self._tensor_names:
- f.write("%s\n" % name)
+ # Save tensor name : tensor id pairs
+ with open(self._dir / 'tensors.json', 'w') as f:
+ json.dump(self._tname_to_tid, f, indent=2)
diff --git a/compiler/visq/visqlib/DumpFakeQuantFM.py b/compiler/visq/visqlib/DumpFakeQuantFM.py
index 024842824..b8dde3831 100644
--- a/compiler/visq/visqlib/DumpFakeQuantFM.py
+++ b/compiler/visq/visqlib/DumpFakeQuantFM.py
@@ -16,9 +16,9 @@
# NOTE This script runs on dalgona
import numpy as np
+import json
from pathlib import Path
-from Util import to_filename
# Fake-quantized Op has the postfix of fq_postfix
# TODO Remove coupling with fake quantization codes
@@ -39,28 +39,46 @@ def _name_before_fq(name):
#
# Before
# self._dir/
-# tensors.txt
+# tensors.json
#
# After
# self._dir/
-# tensors.txt
-# <TENSOR_NAME>.npy
-# NOTE TENSOR_NAME is transformed by to_filename
+# tensors.json
+# <TENSOR_ID>.npy
+# NOTE tensors.json has a dictionary {TENSOR_NAME -> TENSOR_ID}
class DumpFakeQuantFM:
def StartAnalysis(self, args):
self._dir = Path(args)
self._num_data = 0
- with open(self._dir / 'tensors.txt') as f:
- self._target_tensors = set([line.rstrip() for line in f])
+ with open(self._dir / 'tensors.json') as f:
+ self._tname_to_tid = json.load(f)
+ self._scale_map = {}
def EndNetworkExecution(self, outputs: list):
self._num_data += 1
# TODO Use DequantizePost when dalgona supports it
- def DefaultOpPost(self, name, opcode, inputs, output):
+ def DefaultOpPost(self, name, opcode, inputs, outputs):
if opcode == 'Dequantize':
- orig_name = _name_before_fq(name)
- if orig_name in self._target_tensors:
- data_path = self._dir / str(self._num_data)
- data_path.mkdir(parents=False, exist_ok=True)
- np.save(str(data_path / to_filename(orig_name)), output['data'])
+ for output in outputs:
+ name = output['name']
+ data = output['data']
+ orig_name = _name_before_fq(name)
+ if orig_name in self._tname_to_tid:
+ tid = self._tname_to_tid[orig_name]
+ data_path = self._dir / str(self._num_data)
+ data_path.mkdir(parents=False, exist_ok=True)
+ np.save(str(data_path / str(tid)), data)
+ # Save scales (scale is fixed, so saving once)
+ if orig_name not in self._scale_map:
+ assert len(inputs) == 1
+ assert 'quantparam' in inputs[0]
+ assert 'scale' in inputs[0]['quantparam']
+ assert len(inputs[0]['quantparam']['scale']) == 1
+ scale = inputs[0]['quantparam']['scale'][0]
+ self._scale_map[orig_name] = scale
+
+ def EndAnalysis(self):
+ # Dump saved scales into scales.txt
+ with open(self._dir / 'scales.txt', 'w') as f:
+ json.dump(self._scale_map, f)
diff --git a/compiler/visq/visqlib/QErrorComputer.py b/compiler/visq/visqlib/QErrorComputer.py
index c60556f59..46ba3e703 100644
--- a/compiler/visq/visqlib/QErrorComputer.py
+++ b/compiler/visq/visqlib/QErrorComputer.py
@@ -15,44 +15,45 @@
import os
import glob
import numpy as np
+import json
from pathlib import Path
-from visqlib.Util import to_filename
+from collections import defaultdict
class QErrorComputer:
def __init__(self, fp32_dir, fq_dir):
self._fp32_dir = fp32_dir
self._fq_dir = fq_dir
- self.qerror_map = dict()
+ self.qerror_map = defaultdict(float)
self._num_processed_data = 0
def collect_data_path(self, fp32_dir, fq_dir):
# Assumption: FM data are saved as follows
#
# fp32_dir/
- # tensors.txt
+ # tensors.json
# <DATA_INDEX>/
- # <TENSOR_NAME>.npy
+ # <TENSOR_ID>.npy
#
# fq_dir/
- # tensors.txt
+ # tensors.json
# <DATA_INDEX>/
- # <TENSOR_NAME>.npy
+ # <TENSOR_ID>.npy
+ #
+ # NOTE tensors.json has a dictionary {TENSOR_NAME -> TENSOR_ID}
self._num_data = len(list(filter(os.path.isdir, glob.glob(fp32_dir + '/*'))))
if self._num_data != len(list(filter(os.path.isdir, glob.glob(fq_dir + '/*')))):
raise RuntimeError("Number of data mistmatches")
self._num_processed_data += self._num_data
- self._filename_to_tensor = dict()
- with open(Path(fp32_dir) / 'tensors.txt') as f:
- tensors = set([line.rstrip() for line in f])
- for tensor in tensors:
- # Check if filename is unique
- # Fix name finding logic unless
- assert to_filename(tensor) not in self._filename_to_tensor
- self._filename_to_tensor[to_filename(tensor)] = tensor
+ self._tid_to_tname = dict() # {tensor id -> tensor name}
+ with open(Path(fp32_dir) / 'tensors.json') as f:
+ tname_to_tid = json.load(f)
+
+ for tname, tid in tname_to_tid.items():
+ self._tid_to_tname[tid] = tname
# Save paths to fp32 data and fq data for each tensor
# dict
@@ -69,8 +70,8 @@ class QErrorComputer:
fq_data_path = fq_dir + '/' + str(data_idx) + '/' + fp32_path.with_suffix(
'.npy').name
fq_path = Path(fq_data_path)
- filename = fp32_path.stem
- tensor_name = self._filename_to_tensor[filename]
+ tid = int(fp32_path.stem)
+ tensor_name = self._tid_to_tname[tid]
# Only save the tensors which have both fp32 data and fq data
if fq_path.is_file() and fp32_path.is_file():
@@ -112,17 +113,19 @@ class MPEIRComputer(QErrorComputer):
# To prevent this, relaxed PEIR with epsilon(10^(-6)) is used.
rPEIR = PEAK_ERROR / (INTERVAL + 0.000001)
- if tensor_name in self.qerror_map:
- self.qerror_map[tensor_name] += rPEIR
- else:
- self.qerror_map[tensor_name] = rPEIR
+ self.qerror_map[tensor_name] += rPEIR
+ # Return
+ # qerror_map (dict: tensor_name(string) -> qerror(float))
+ # qerror_min (float)
+ # qerror_max (float)
def get_final_result(self):
qerror_map = dict()
for tensor_name, acc in self.qerror_map.items():
qerror_map[tensor_name] = acc / self._num_processed_data
- return qerror_map
+ # Fixed qerror_min (0), qerror_max (1)
+ return qerror_map, 0.0, 1.0
def run(self):
self.advance_on(self._fp32_dir, self._fq_dir)
@@ -145,14 +148,15 @@ class MSEComputer(QErrorComputer):
MSE = np.square(fp32_data - fq_data).mean()
- if tensor_name in self.qerror_map:
- self.qerror_map[tensor_name] += MSE
- else:
- self.qerror_map[tensor_name] = MSE
+ self.qerror_map[tensor_name] += MSE
self.qerror_min = min(MSE, self.qerror_min)
self.qerror_max = max(MSE, self.qerror_max)
+ # Return
+ # qerror_map (dict: tensor_name(string) -> qerror(float))
+ # qerror_min (float)
+ # qerror_max (float)
def get_final_result(self):
qerror_map = dict()
for tensor_name, acc in self.qerror_map.items():
@@ -181,14 +185,15 @@ class TAEComputer(QErrorComputer): #total absolute error
total_error = np.sum(np.abs(fp32_data - fq_data))
- if tensor_name in self.qerror_map:
- self.qerror_map[tensor_name] += total_error
- else:
- self.qerror_map[tensor_name] = total_error
+ self.qerror_map[tensor_name] += total_error
self.qerror_min = min(total_error, self.qerror_min)
self.qerror_max = max(total_error, self.qerror_max)
+ # Return
+ # qerror_map (dict: tensor_name(string) -> qerror(float))
+ # qerror_min (float)
+ # qerror_max (float)
def get_final_result(self):
qerror_map = dict()
for tensor_name, acc in self.qerror_map.items():
@@ -198,3 +203,52 @@ class TAEComputer(QErrorComputer): #total absolute error
def run(self):
self.advance_on(self._fp32_dir, self._fq_dir)
return self.get_final_result()
+
+
+# Scaled Root Mean Square Error (SRMSE)
+# SRMSE = sqrt(MSE) / scale
+class SRMSEComputer(QErrorComputer):
+ def __init__(self, fp32_dir, fq_dir):
+ super().__init__(fp32_dir, fq_dir)
+ if fq_dir != None:
+ self.scale_file = Path(fq_dir) / 'scales.txt'
+
+ # Incrementally compute Qerror while traversing all data in fp32_dir and fq_dir
+ def advance_on(self, fp32_dir, fq_dir):
+ if fq_dir != None:
+ self.scale_file = Path(fq_dir) / 'scales.txt'
+ self._fq_dir = fq_dir
+
+ data_paths = self.collect_data_path(fp32_dir, fq_dir)
+
+ for tensor_name, data_path in data_paths.items():
+ for (fp32_data_path, fq_data_path) in data_path:
+ fp32_data = np.load(fp32_data_path)
+ fq_data = np.load(fq_data_path)
+
+ MSE = np.square(fp32_data - fq_data).mean()
+
+ self.qerror_map[tensor_name] += MSE
+
+ # Return
+ # qerror_map (dict: tensor_name(string) -> qerror(float))
+ # qerror_min (float)
+ # qerror_max (float)
+ def get_final_result(self):
+ with open(self.scale_file) as f:
+ # scale_map: {tensor_name(str) -> scale(float)}
+ scale_map = json.load(f)
+
+ qerror_max = 0.0
+ qerror_map = dict()
+ for tensor_name, acc in self.qerror_map.items():
+ MSE = acc / self._num_processed_data
+ SRMSE = np.sqrt(MSE) / scale_map[tensor_name]
+ qerror_map[tensor_name] = SRMSE
+ qerror_max = max(SRMSE, qerror_max)
+
+ return qerror_map, 0.0, qerror_max
+
+ def run(self):
+ self.advance_on(self._fp32_dir, self._fq_dir)
+ return self.get_final_result()
diff --git a/compute/ARMComputeEx/src/runtime/CL/functions/CLSplitVEx.cpp b/compute/ARMComputeEx/src/runtime/CL/functions/CLSplitVEx.cpp
index 73f5f6eb1..bca4d5cb6 100644
--- a/compute/ARMComputeEx/src/runtime/CL/functions/CLSplitVEx.cpp
+++ b/compute/ARMComputeEx/src/runtime/CL/functions/CLSplitVEx.cpp
@@ -174,7 +174,7 @@ void CLSplitVEx::configure(const ICLTensor *input, const ICLTensor *size_splits,
// Extract output tensor info
std::vector<ITensorInfo *> outputs_info;
- for (auto &output : _outputs)
+ for (auto &&output : _outputs)
{
ARM_COMPUTE_ERROR_ON_NULLPTR(output);
outputs_info.emplace_back(output->info());
diff --git a/compute/cker/CMakeLists.txt b/compute/cker/CMakeLists.txt
index ce328b685..d464dccae 100644
--- a/compute/cker/CMakeLists.txt
+++ b/compute/cker/CMakeLists.txt
@@ -12,6 +12,10 @@ if(PROFILE_RUY)
target_link_libraries(nnfw_lib_cker INTERFACE ruy_profiler)
endif(PROFILE_RUY)
+if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)")
+ target_compile_definitions(nnfw_lib_cker INTERFACE CKER_X86_PLATFORM)
+endif(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)")
+
target_include_directories(nnfw_lib_cker INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include)
# Workaround to avoid warning
diff --git a/compute/cker/include/cker/PortableTensorUtils.h b/compute/cker/include/cker/PortableTensorUtils.h
index 2a58a2ec9..7e4b01a01 100644
--- a/compute/cker/include/cker/PortableTensorUtils.h
+++ b/compute/cker/include/cker/PortableTensorUtils.h
@@ -144,6 +144,60 @@ inline void PortableSymmetricQuantizeFloats(const float *values, const int size,
}
}
+inline void PortableAsymmetricQuantizeFloats(const float *values, const int size,
+ int8_t *quantized_values, float *scaling_factor,
+ int32_t *offset)
+{
+ /* Copied from TensorFlow PortableAsymmetricQuantizeFloats */
+ const int32_t kMinScale = -128;
+ const int32_t kMaxScale = 127;
+ const double qmin_double = kMinScale;
+ const double qmax_double = kMaxScale;
+ const auto minmax = std::minmax_element(values, values + size);
+ const double rmin = static_cast<double>(std::min(0.0f, *minmax.first));
+ const double rmax = static_cast<double>(std::max(0.0f, *minmax.second));
+ if (rmin == rmax)
+ {
+ memset(quantized_values, 0, size * sizeof(int8_t));
+ *scaling_factor = 1;
+ *offset = 0;
+ return;
+ }
+ else
+ {
+ double scale = (rmax - rmin) / (qmax_double - qmin_double);
+ const double zero_point_from_min = qmin_double - rmin / scale;
+ const double zero_point_from_max = qmax_double - rmax / scale;
+ const double zero_point_from_min_error = std::abs(qmin_double) + std::abs(rmin / scale);
+ const double zero_point_from_max_error = std::abs(qmax_double) + std::abs(rmax / scale);
+ const double zero_point_double = zero_point_from_min_error < zero_point_from_max_error
+ ? zero_point_from_min
+ : zero_point_from_max;
+ int8_t nudged_zero_point = 0;
+ if (zero_point_double <= qmin_double)
+ {
+ nudged_zero_point = kMinScale;
+ }
+ else if (zero_point_double >= qmax_double)
+ {
+ nudged_zero_point = kMaxScale;
+ }
+ else
+ {
+ nudged_zero_point = static_cast<int8_t>(round(zero_point_double));
+ }
+ *scaling_factor = scale;
+ *offset = nudged_zero_point;
+ }
+ const float scaling_factor_inv = 1.0f / *scaling_factor;
+ for (int i = 0; i < size; ++i)
+ {
+ const int32_t quantized_value =
+ static_cast<int32_t>(std::round(*offset + values[i] * scaling_factor_inv));
+ quantized_values[i] = std::min(kMaxScale, std::max(kMinScale, quantized_value));
+ }
+}
+
inline void PortableMatrixBatchVectorMultiplyAccumulate(const int8_t *__restrict__ matrix,
const int m_rows, const int m_cols,
const int8_t *__restrict__ vectors,
diff --git a/compute/cker/include/cker/Shape.h b/compute/cker/include/cker/Shape.h
index 86caf7d18..9269ce9aa 100644
--- a/compute/cker/include/cker/Shape.h
+++ b/compute/cker/include/cker/Shape.h
@@ -156,7 +156,7 @@ public:
const int dimensions_count = std::distance(src_iterable.begin(), src_iterable.end());
Resize(dimensions_count);
int32_t *data = DimsData();
- for (auto it : src_iterable)
+ for (auto &&it : src_iterable)
{
*data = it;
++data;
diff --git a/compute/cker/include/cker/Types.h b/compute/cker/include/cker/Types.h
index 495c89440..3fd0cf5b6 100644
--- a/compute/cker/include/cker/Types.h
+++ b/compute/cker/include/cker/Types.h
@@ -258,9 +258,12 @@ struct FullyConnectedParams
// uint8, etc, activation params.
int32_t quantized_activation_min;
int32_t quantized_activation_max;
- // float activation params - no one use this params, but ruy might use them later.
- // float float_activation_min;
- // float float_activation_max;
+ // float activation params
+ float float_activation_min;
+ float float_activation_max;
+ // Mark the operands as cacheable if they are unchanging, e.g. weights.
+ bool lhs_cacheable;
+ bool rhs_cacheable;
// FullyConnectedWeightsFormat weights_format;
};
diff --git a/compute/cker/include/cker/eigen/eigen_gemm_eigen.h b/compute/cker/include/cker/eigen/eigen_gemm_eigen.h
new file mode 100644
index 000000000..d4f8fc09d
--- /dev/null
+++ b/compute/cker/include/cker/eigen/eigen_gemm_eigen.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __NNFW_CKER_EGIEN_EIGEN_GEMM_EIGEN_H__
+#define __NNFW_CKER_EGIEN_EIGEN_GEMM_EIGEN_H__
+
+// See b/131835803: in TFLite code, because eigen_spatial_convolutions.h does
+// #define Eigen EigenForTFLite, it is difficult to have any #include of Eigen
+// headers in a header file, as that results in name classes (compilation
+// errors) depending on the order in which these headers are #included.
+// So we have moved the #include of Eigen here, in a .cc file, where we have
+// control over the header #include sequence.
+// #include "third_party/eigen3/Eigen/Core"
+// #include "tensorflow/lite/kernels/cpu_backend_context.h"
+// #include "tensorflow/lite/kernels/cpu_backend_gemm_params.h"
+// #include "tensorflow/lite/kernels/internal/common.h"
+// #include "cker/eigen/eigen_convolution_helpers.h"
+#include "cker/operation/Common.h"
+#include "cker/Types.h"
+
+#include <Eigen/Core>
+
+namespace nnfw
+{
+namespace cker
+{
+namespace detail
+{
+
+// tensorflow/tensorflow/lite/kernels/cpu_backend_gemm_eigen.h and cpu_backend_gemm_eigen.cc
+struct GemmImplUsingEigen
+{
+ static void Run(const MatrixParams<float> &lhs_params, const float *lhs_data,
+ const MatrixParams<float> &rhs_params, const float *rhs_data,
+ const MatrixParams<float> &dst_params, float *dst_data,
+ const GemmParams<float, float> &params)
+ {
+ // This code assumes specific storage orders, encoded in these Eigen types.
+ // These assumptions have been checked by TF_LITE_ASSERT's in the public
+ // Gemm entry point already, before the implementation gets to this point.
+ using EigenMatrixMapRowMajorConst =
+ Eigen::Map<const Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>;
+ using EigenMatrixMapColMajorConst =
+ Eigen::Map<const Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>>;
+ using EigenMatrixMapColMajorMutable =
+ Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>>;
+
+ EigenMatrixMapRowMajorConst eigen_lhs(lhs_data, lhs_params.rows, lhs_params.cols);
+ EigenMatrixMapColMajorConst eigen_rhs(rhs_data, rhs_params.rows, rhs_params.cols);
+ EigenMatrixMapColMajorMutable eigen_dst(dst_data, dst_params.rows, dst_params.cols);
+
+ if (rhs_params.cols == 1)
+ {
+ eigen_dst.col(0).noalias() = eigen_lhs * eigen_rhs.col(0);
+ }
+ else if (lhs_params.rows == 1)
+ {
+ eigen_dst.row(0).noalias() = eigen_lhs.row(0) * eigen_rhs;
+ }
+ else
+ {
+ eigen_dst.noalias() = eigen_lhs * eigen_rhs;
+ }
+
+ if (params.bias)
+ {
+ BiasAndClamp(params.clamp_min, params.clamp_max, dst_params.rows, params.bias,
+ dst_params.rows * dst_params.cols, dst_data);
+ }
+ else
+ {
+ eigen_dst = eigen_dst.cwiseMin(params.clamp_max).cwiseMax(params.clamp_min);
+ }
+ }
+};
+
+} // namespace detail
+} // namespace cker
+} // namespace nnfw
+
+#endif // __NNFW_CKER_EGIEN_EIGEN_GEMM_EIGEN_H__
diff --git a/compute/cker/include/cker/operation/Conv.h b/compute/cker/include/cker/operation/Conv.h
index 7cd54dcd5..2572b51ee 100644
--- a/compute/cker/include/cker/operation/Conv.h
+++ b/compute/cker/include/cker/operation/Conv.h
@@ -207,6 +207,21 @@ private:
std::vector<int32_t> _per_channel_output_multiplier;
std::vector<int> _per_channel_output_shift;
};
+
+struct ConvHybridTempArena
+{
+ ConvHybridTempArena(int batch_size, int input_size)
+ {
+ input_quantized.resize(input_size);
+ // TODO: Optimize the case of batch_size = 1
+ input_scaling_factors.resize(batch_size);
+ input_offsets.resize(batch_size);
+ }
+ std::vector<int8_t> input_quantized;
+ std::vector<float> input_scaling_factors;
+ std::vector<int32_t> input_offsets;
+};
+
} // namespace cker
} // namespace nnfw
diff --git a/compute/cker/include/cker/operation/DepthwiseConv.h b/compute/cker/include/cker/operation/DepthwiseConv.h
index ed1f93d44..c926ec4f1 100644
--- a/compute/cker/include/cker/operation/DepthwiseConv.h
+++ b/compute/cker/include/cker/operation/DepthwiseConv.h
@@ -26,6 +26,7 @@
#include "cker/operation/optimized/DepthwiseConvUint8.h"
#include "cker/operation/optimized/integer_ops/DepthwiseConvInt8.h"
#include "cker/operation/reference/integer_ops/DepthwiseConvUInt8.h"
+#include "cker/operation/reference/integer_ops/DepthwiseConvHybrid.h"
#include "cker/CpuBackendThreadpool.h"
namespace nnfw
diff --git a/compute/cker/include/cker/operation/Einsum.h b/compute/cker/include/cker/operation/Einsum.h
index 6721a7508..bb9f88f8d 100644
--- a/compute/cker/include/cker/operation/Einsum.h
+++ b/compute/cker/include/cker/operation/Einsum.h
@@ -274,7 +274,7 @@ public:
}
for (int i = 0; i < num_inputs; ++i)
{
- for (int label : free_labels[i])
+ for (auto &&label : free_labels[i])
{
result_labels.push_back(label);
result_shape_dims.push_back(label_to_dim_sizes[label]);
@@ -300,7 +300,7 @@ public:
{
// We inflated the output. Modify result labels accordingly.
Labels inflated_labels;
- for (int label : result_labels)
+ for (auto &&label : result_labels)
{
inflated_labels.insert(inflated_labels.end(), output_label_counts[label], label);
}
@@ -775,7 +775,7 @@ private:
Shape inflated_shape;
std::vector<int32_t> strided_shape_dims;
std::vector<int32_t> inflated_shape_dims;
- for (int label : labels)
+ for (auto &&label : labels)
{
const int32_t count = label_counts[label];
const int current_axis =
diff --git a/compute/cker/include/cker/operation/FullyConnected.h b/compute/cker/include/cker/operation/FullyConnected.h
index b7d27e85d..71a2f19ef 100644
--- a/compute/cker/include/cker/operation/FullyConnected.h
+++ b/compute/cker/include/cker/operation/FullyConnected.h
@@ -21,6 +21,7 @@
#include <ruy/context.h>
#include "cker/operation/FullyConnectedDense16x1.h"
#include "cker/operation/FullyConnectedSparse16x1.h"
+#include "cker/operation/optimized/Gemm.h"
#include "cker/Shape.h"
#include "cker/Types.h"
#include "cker/Utils.h"
@@ -58,6 +59,42 @@ public:
std::vector<int32_t> accum_scratch;
};
+#if defined(CKER_X86_PLATFORM)
+
+// From tensorflow/tensorflow/lite/kernels/internal/optimized/optimized_ops.h
+inline void FullyConnected(const FullyConnectedParams &params, const Shape &input_shape,
+ const float *input_data, const Shape &weights_shape,
+ const float *weights_data, const Shape &,
+ const float *optional_bias_data, const Shape &output_shape,
+ float *output_data)
+{
+ const int dims_count = weights_shape.DimensionsCount();
+ const int input_rows = weights_shape.Dims(dims_count - 1);
+ MatrixParams<float> rhs_params;
+ rhs_params.order = Order::kColMajor;
+ rhs_params.rows = input_rows;
+ rhs_params.cols = input_shape.FlatSize() / input_rows;
+ rhs_params.cache_policy = optimized::DefaultCachePolicy(params.rhs_cacheable);
+
+ MatrixParams<float> lhs_params;
+ lhs_params.order = Order::kRowMajor;
+ lhs_params.cols = weights_shape.Dims(dims_count - 1);
+ lhs_params.rows = FlatSizeSkipDim(weights_shape, dims_count - 1);
+ lhs_params.cache_policy = optimized::DefaultCachePolicy(params.lhs_cacheable);
+ MatrixParams<float> dst_params;
+ dst_params.order = Order::kColMajor;
+ dst_params.rows = output_shape.Dims(output_shape.DimensionsCount() - 1);
+ dst_params.cols = FlatSizeSkipDim(output_shape, output_shape.DimensionsCount() - 1);
+ GemmParams<float, float> gemm_params;
+ gemm_params.bias = optional_bias_data;
+ gemm_params.clamp_min = params.float_activation_min;
+ gemm_params.clamp_max = params.float_activation_max;
+ optimized::Gemm(lhs_params, weights_data, rhs_params, input_data, dst_params, output_data,
+ gemm_params);
+}
+
+#else // CKER_X86_PLATFORM
+
inline void FullyConnected(const FullyConnectedParams &params, const Shape &input_shape,
const float *input_data, const Shape &weights_shape,
const float *weights_data, const Shape &, const float *bias_data,
@@ -89,6 +126,8 @@ inline void FullyConnected(const FullyConnectedParams &params, const Shape &inpu
}
}
+#endif // CKER_X86_PLATFORM
+
inline void FullyConnected(const FullyConnectedParams &params, const Shape &input_shape,
const uint8_t *input_data, const Shape &filter_shape,
const uint8_t *filter_data, const Shape &bias_shape,
diff --git a/compute/cker/include/cker/operation/optimized/Gemm.h b/compute/cker/include/cker/operation/optimized/Gemm.h
new file mode 100644
index 000000000..cfebef452
--- /dev/null
+++ b/compute/cker/include/cker/operation/optimized/Gemm.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __NNFW_CKER_OPTIMIZED_GEMM_H__
+#define __NNFW_CKER_OPTIMIZED_GEMM_H__
+
+#include "cker/eigen/eigen_gemm_eigen.h"
+#include "cker/Shape.h"
+#include "cker/Types.h"
+
+#include <ruy/context.h>
+
+namespace nnfw
+{
+namespace cker
+{
+namespace optimized
+{
+
+#if defined(CKER_X86_PLATFORM)
+
+/* From tensorflow/tensorflow/lite/kernels/cpu_backend_gemm_x86.h */
+template <typename LhsScalar, typename RhsScalar, typename AccumScalar, typename DstScalar,
+ QuantizationFlavor quantization_flavor>
+struct GemmImplX86
+{
+ static void Run(const MatrixParams<LhsScalar> &, const LhsScalar *,
+ const MatrixParams<RhsScalar> &, const RhsScalar *,
+ const MatrixParams<DstScalar> &, DstScalar *,
+ const GemmParams<AccumScalar, DstScalar, quantization_flavor> &)
+ {
+ static_assert(
+ std::is_floating_point<LhsScalar>::value && std::is_floating_point<RhsScalar>::value &&
+ std::is_floating_point<AccumScalar>::value && std::is_floating_point<DstScalar>::value &&
+ quantization_flavor != QuantizationFlavor::kFloatingPoint,
+ "GemmImplX86 does not supported types other than float yet.");
+ }
+};
+
+// For float, defer to eigen for now.
+template <> struct GemmImplX86<float, float, float, float, QuantizationFlavor::kFloatingPoint>
+{
+ static void Run(const MatrixParams<float> &lhs_params, const float *lhs_data,
+ const MatrixParams<float> &rhs_params, const float *rhs_data,
+ const MatrixParams<float> &dst_params, float *dst_data,
+ const GemmParams<float, float, QuantizationFlavor::kFloatingPoint> &params)
+ {
+ detail::GemmImplUsingEigen::Run(lhs_params, lhs_data, rhs_params, rhs_data, dst_params,
+ dst_data, params);
+ }
+};
+
+/* From tensorflow/tensorflow/lite/kernels/cpu_backend_gemm.h */
+/* GEMM dispatch implementation for x86.
+ */
+template <typename LhsScalar, typename RhsScalar, typename AccumScalar, typename DstScalar,
+ QuantizationFlavor quantization_flavor>
+struct GemmImpl : GemmImplX86<LhsScalar, RhsScalar, AccumScalar, DstScalar, quantization_flavor>
+{
+};
+
+/* From tensorflow/tensorflow/lite/kernels/cpu_backend_gemm.h */
+template <typename LhsScalar, typename RhsScalar, typename AccumScalar, typename DstScalar,
+ QuantizationFlavor quantization_flavor>
+void Gemm(const MatrixParams<LhsScalar> &lhs_params, const LhsScalar *lhs_data,
+ const MatrixParams<RhsScalar> &rhs_params, const RhsScalar *rhs_data,
+ const MatrixParams<DstScalar> &dst_params, DstScalar *dst_data,
+ const GemmParams<AccumScalar, DstScalar, quantization_flavor> &params)
+{
+ // Generic case: dispatch to any backend as a general GEMM.
+ GemmImpl<LhsScalar, RhsScalar, AccumScalar, DstScalar, quantization_flavor>::Run(
+ lhs_params, lhs_data, rhs_params, rhs_data, dst_params, dst_data, params);
+}
+
+// From tensorflow/tensorflow/lite/kernels/cpu_backend_gemm_params.h
+inline CachePolicy DefaultCachePolicy(bool is_constant_data)
+{
+ return is_constant_data ? CachePolicy::kCacheIfLargeSpeedup : CachePolicy::kNeverCache;
+}
+#endif // CKER_X86_PLATFORM
+
+} // namespace optimized
+} // namespace cker
+} // namespace nnfw
+
+#endif // __NNFW_CKER_OPTIMIZED_GEMM_H__
diff --git a/compute/cker/include/cker/operation/reference/Conv.h b/compute/cker/include/cker/operation/reference/Conv.h
index 8bfd4694e..e316083a5 100644
--- a/compute/cker/include/cker/operation/reference/Conv.h
+++ b/compute/cker/include/cker/operation/reference/Conv.h
@@ -311,6 +311,91 @@ inline void Conv(const ConvParams &params, const int32_t *output_multiplier,
}
}
+// Slightly modified from tflite 2.13.0 HybridConvPerChannel
+// im2col and im2col_shape are removed since it is not used in reference kernel.
+inline void HybridConvPerChannel(const ConvParams &params, float *scaling_factors_ptr,
+ const Shape &input_shape, const int8_t *input_data,
+ const Shape &filter_shape, const int8_t *filter_data,
+ const Shape &bias_shape, const float *bias_data,
+ const Shape &output_shape, float *output_data,
+ const float *per_channel_scale, const int32_t *input_offset)
+
+{
+ const int stride_width = params.stride_width;
+ const int stride_height = params.stride_height;
+ const int dilation_width_factor = params.dilation_width_factor;
+ const int dilation_height_factor = params.dilation_height_factor;
+ const int pad_width = params.padding_values.width;
+ const int pad_height = params.padding_values.height;
+ const float output_activation_min = params.float_activation_min;
+ const float output_activation_max = params.float_activation_max;
+ assert(input_shape.DimensionsCount() == 4);
+ assert(filter_shape.DimensionsCount() == 4);
+ assert(output_shape.DimensionsCount() == 4);
+ const int batches = MatchingDim(input_shape, 0, output_shape, 0);
+ const int input_depth = input_shape.Dims(3);
+ const int output_depth = MatchingDim(filter_shape, 0, output_shape, 3);
+ if (bias_data)
+ {
+ assert(bias_shape.FlatSize() == output_depth);
+ UNUSED_RELEASE(bias_shape);
+ }
+ const int input_height = input_shape.Dims(1);
+ const int input_width = input_shape.Dims(2);
+ const int filter_height = filter_shape.Dims(1);
+ const int filter_width = filter_shape.Dims(2);
+ const int filter_input_depth = filter_shape.Dims(3);
+ const int groups = input_depth / filter_input_depth;
+ assert(input_depth % filter_input_depth == 0);
+ const int filters_per_group = output_depth / groups;
+ const int output_height = output_shape.Dims(1);
+ const int output_width = output_shape.Dims(2);
+ for (int batch = 0; batch < batches; ++batch)
+ {
+ for (int out_y = 0; out_y < output_height; ++out_y)
+ {
+ for (int out_x = 0; out_x < output_width; ++out_x)
+ {
+ for (int out_channel = 0; out_channel < output_depth; ++out_channel)
+ {
+ auto group = out_channel / filters_per_group;
+ const int in_x_origin = (out_x * stride_width) - pad_width;
+ const int in_y_origin = (out_y * stride_height) - pad_height;
+ int32_t acc = 0;
+ for (int filter_y = 0; filter_y < filter_height; ++filter_y)
+ {
+ for (int filter_x = 0; filter_x < filter_width; ++filter_x)
+ {
+ for (int in_channel = 0; in_channel < filter_input_depth; ++in_channel)
+ {
+ const int in_x = in_x_origin + dilation_width_factor * filter_x;
+ const int in_y = in_y_origin + dilation_height_factor * filter_y;
+ // If the location is outside the bounds of the input image,
+ // use zero as a default value.
+ if ((in_x >= 0) && (in_x < input_width) && (in_y >= 0) && (in_y < input_height))
+ {
+ int32_t input_val = input_data[Offset(input_shape, batch, in_y, in_x,
+ in_channel + group * filter_input_depth)];
+ int32_t filter_val =
+ filter_data[Offset(filter_shape, out_channel, filter_y, filter_x, in_channel)];
+ acc += filter_val * (input_val - input_offset[batch]);
+ }
+ }
+ }
+ }
+ float acc_float = acc * per_channel_scale[out_channel] * scaling_factors_ptr[batch];
+ if (bias_data)
+ {
+ acc_float += bias_data[out_channel];
+ }
+ output_data[Offset(output_shape, batch, out_y, out_x, out_channel)] =
+ ActivationFunctionWithMinMax(acc_float, output_activation_min, output_activation_max);
+ }
+ }
+ }
+ }
+}
+
} // namespace reference
} // namespace cker
} // namespace nnfw
diff --git a/compute/cker/include/cker/operation/reference/integer_ops/DepthwiseConvHybrid.h b/compute/cker/include/cker/operation/reference/integer_ops/DepthwiseConvHybrid.h
new file mode 100644
index 000000000..9fc58ad3b
--- /dev/null
+++ b/compute/cker/include/cker/operation/reference/integer_ops/DepthwiseConvHybrid.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __NNFW_CKER_REFERENCE_DEPTHWISE_CONV_HYBRID_H__
+#define __NNFW_CKER_REFERENCE_DEPTHWISE_CONV_HYBRID_H__
+
+#include "cker/Shape.h"
+#include "cker/Types.h"
+#include "cker/Utils.h"
+
+namespace nnfw
+{
+namespace cker
+{
+namespace reference_integer_ops
+{
+
+inline void DepthwiseConvHybridPerChannel(const DepthwiseConvParams &params,
+ float *scaling_factors_ptr, const Shape &input_shape,
+ const int8_t *input_data, const Shape &filter_shape,
+ const int8_t *filter_data, const Shape &bias_shape,
+ const float *bias_data, const Shape &output_shape,
+ float *output_data, const float *per_channel_scale,
+ int32_t *input_offset)
+{
+ const int stride_width = params.stride_width;
+ const int stride_height = params.stride_height;
+ const int dilation_width_factor = params.dilation_width_factor;
+ const int dilation_height_factor = params.dilation_height_factor;
+ const int pad_width = params.padding_values.width;
+ const int pad_height = params.padding_values.height;
+ const int depth_multiplier = params.depth_multiplier;
+ const float output_activation_min = params.float_activation_min;
+ const float output_activation_max = params.float_activation_max;
+
+ // Check dimensions of the tensors.
+ assert(input_shape.DimensionsCount() == 4);
+ assert(filter_shape.DimensionsCount() == 4);
+ assert(output_shape.DimensionsCount() == 4);
+
+ const int batches = MatchingDim(input_shape, 0, output_shape, 0);
+ const int output_depth = MatchingDim(filter_shape, 3, output_shape, 3);
+ const int input_height = input_shape.Dims(1);
+ const int input_width = input_shape.Dims(2);
+ const int input_depth = input_shape.Dims(3);
+ const int filter_height = filter_shape.Dims(1);
+ const int filter_width = filter_shape.Dims(2);
+ const int output_height = output_shape.Dims(1);
+ const int output_width = output_shape.Dims(2);
+ const int bias_depth = bias_shape.FlatSize();
+ UNUSED_RELEASE(output_depth);
+ UNUSED_RELEASE(bias_shape);
+ assert(output_depth == input_depth * depth_multiplier);
+ assert(bias_depth == output_depth);
+
+ for (int batch = 0; batch < batches; ++batch)
+ {
+ for (int out_y = 0; out_y < output_height; ++out_y)
+ {
+ for (int out_x = 0; out_x < output_width; ++out_x)
+ {
+ for (int in_channel = 0; in_channel < input_depth; ++in_channel)
+ {
+ for (int m = 0; m < depth_multiplier; ++m)
+ {
+ const int output_channel = m + in_channel * depth_multiplier;
+ const int in_x_origin = (out_x * stride_width) - pad_width;
+ const int in_y_origin = (out_y * stride_height) - pad_height;
+ int32_t acc = 0;
+ for (int filter_y = 0; filter_y < filter_height; ++filter_y)
+ {
+ for (int filter_x = 0; filter_x < filter_width; ++filter_x)
+ {
+ const int in_x = in_x_origin + dilation_width_factor * filter_x;
+ const int in_y = in_y_origin + dilation_height_factor * filter_y;
+ // Zero padding by omitting the areas outside the image.
+ const bool is_point_inside_image =
+ (in_x >= 0) && (in_x < input_width) && (in_y >= 0) && (in_y < input_height);
+ if (is_point_inside_image)
+ {
+ int32_t input_val =
+ input_data[Offset(input_shape, batch, in_y, in_x, in_channel)];
+ int32_t filter_val =
+ filter_data[Offset(filter_shape, 0, filter_y, filter_x, output_channel)];
+ acc += filter_val * (input_val - input_offset[batch]);
+ }
+ }
+ }
+ float acc_float = static_cast<float>(acc);
+ acc_float *= per_channel_scale[output_channel] * scaling_factors_ptr[batch];
+ if (bias_data && output_channel < bias_depth)
+ {
+ acc_float += bias_data[output_channel];
+ }
+ output_data[Offset(output_shape, batch, out_y, out_x, output_channel)] =
+ ActivationFunctionWithMinMax(acc_float, output_activation_min, output_activation_max);
+ }
+ }
+ }
+ }
+ }
+}
+
+} // namespace reference_integer_ops
+} // namespace cker
+} // namespace nnfw
+
+#endif // __NNFW_CKER_REFERENCE_DEPTHWISE_CONV_HYBRID_H__
diff --git a/compute/cker/include/cker/train/operation/FullyConnected.h b/compute/cker/include/cker/train/operation/FullyConnected.h
new file mode 100644
index 000000000..b0255d287
--- /dev/null
+++ b/compute/cker/include/cker/train/operation/FullyConnected.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __NNFW_CKER_TRAIN_OPERATION_FULLY_CONNECTED_H__
+#define __NNFW_CKER_TRAIN_OPERATION_FULLY_CONNECTED_H__
+
+#include "cker/eigen/Utils.h"
+#include "cker/Shape.h"
+
+namespace nnfw
+{
+namespace cker
+{
+namespace train
+{
+
+template <typename T>
+inline void FullyConnectedBiasGrad(const Shape &incomming_shape, const T *incomming_data,
+ const Shape &grad_shape, T *grad_data)
+{
+ const auto bias_size = grad_shape.FlatSize();
+ if (bias_size != incomming_shape.Dims(incomming_shape.DimensionsCount() - 1) ||
+ bias_size != grad_shape.Dims(0))
+ throw std::runtime_error("cker::FullyConnectedBiasGrad: Unmatched shape");
+
+ const auto in_mat = MapAsMatrixWithLastDimAsRows(incomming_data, incomming_shape);
+ auto grad_mat = MapAsMatrixWithLastDimAsRows(grad_data, grad_shape);
+
+ grad_mat = in_mat.rowwise().sum();
+}
+
+} // namespace train
+} // namespace cker
+} // namespace nnfw
+
+#endif // __NNFW_CKER_FULLY_CONNECTED_H__
diff --git a/compute/cker/include/cker/train/operation/Loss.h b/compute/cker/include/cker/train/operation/Loss.h
new file mode 100644
index 000000000..94f49ff07
--- /dev/null
+++ b/compute/cker/include/cker/train/operation/Loss.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __NNFW_CKER_TRAIN_OPERATION_LOSS_H__
+#define __NNFW_CKER_TRAIN_OPERATION_LOSS_H__
+
+#include "cker/Shape.h"
+#include "cker/eigen/Utils.h"
+
+namespace nnfw
+{
+namespace cker
+{
+namespace train
+{
+
+template <typename T>
+inline void MSE(const Shape &y_pred_shape, const T *y_pred_data, const Shape &y_true_shape,
+ const T *y_true_data, const Shape &output_shape, T *output_data)
+{
+ // TODO Consider Reduction
+ if (output_shape != Shape{1})
+ throw std::runtime_error("cker::MSE: output_shape != Shape{1}");
+ if (y_pred_shape != y_true_shape)
+ throw std::runtime_error("cker::MSE: y_pred_shape != y_true_shape");
+
+ const auto y_pred = MapAsMatrixWithLastDimAsRows(y_pred_data, y_pred_shape);
+ const auto y_true = MapAsMatrixWithLastDimAsRows(y_true_data, y_true_shape);
+
+ double squared_sum = 0.0f;
+ for (size_t c = 0; c < (size_t)y_pred.cols(); ++c)
+ {
+ for (size_t r = 0; r < (size_t)y_pred.rows(); ++r)
+ {
+ double error = y_pred.coeff(r, c) - y_true.coeff(r, c);
+ squared_sum += (error * error);
+ }
+ }
+
+ auto size = y_pred.cols() * y_pred.rows();
+ output_data[0] = (T)(squared_sum / size);
+}
+
+template <typename T>
+inline void MSEGrad(const Shape &y_pred_shape, const T *y_pred_data, const Shape &y_true_shape,
+ const T *y_true_data, const Shape &grad_shape, T *grad_data)
+{
+ if (y_pred_shape != y_true_shape)
+ throw std::runtime_error("cker::MSEGrad: y_pred_shape != y_true_shape");
+ if (y_pred_shape != grad_shape)
+ throw std::runtime_error("cker::MSEGrad: y_pred_shape != grad_shape");
+
+ const int size = grad_shape.FlatSize();
+ for (int i = 0; i < size; ++i)
+ {
+ grad_data[i] = static_cast<T>(-2 * (y_true_data[i] - y_pred_data[i]) / size);
+ }
+}
+
+} // namespace train
+} // namespace cker
+} // namespace nnfw
+
+#endif // __NNFW_CKER_TRAIN_OPERATION_LOSS_H__
diff --git a/compute/cker/include/cker/train/operation/ReLU.h b/compute/cker/include/cker/train/operation/ReLU.h
new file mode 100644
index 000000000..32cf7fa9c
--- /dev/null
+++ b/compute/cker/include/cker/train/operation/ReLU.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __NNFW_CKER_TRAIN_OPERATION_RELU_H__
+#define __NNFW_CKER_TRAIN_OPERATION_RELU_H__
+
+#include "cker/Shape.h"
+#include "cker/eigen/Utils.h"
+
+#include <Eigen/Core>
+
+namespace nnfw
+{
+namespace cker
+{
+namespace train
+{
+
+inline void ReLUGrad(const Shape &output_shape, const float *output_data,
+ const Shape &incoming_shape, const float *incoming_data,
+ const Shape &grad_shape, float *grad_data)
+{
+ const auto output_map = MapAsVector(output_data, output_shape);
+ const auto incoming_map = MapAsVector(incoming_data, incoming_shape);
+ auto grad_map = MapAsVector(grad_data, grad_shape);
+
+ if (output_shape == incoming_shape && output_shape == grad_shape)
+ grad_map.array() = incoming_map.array() * (output_map.array() > 0.0f).template cast<float>();
+ else
+ throw std::runtime_error("cker::ReLUGrad: Unsupported shape");
+}
+
+} // namespace train
+} // namespace cker
+} // namespace nnfw
+
+#endif // __NNFW_CKER_TRAIN_OPERATION_RELU_H__
diff --git a/compute/cker/src/train/FullyConnected.test.cc b/compute/cker/src/train/FullyConnected.test.cc
new file mode 100644
index 000000000..37c2d4a97
--- /dev/null
+++ b/compute/cker/src/train/FullyConnected.test.cc
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cker/train/operation/FullyConnected.h>
+
+#include <gtest/gtest.h>
+#include <vector>
+
+TEST(CKer_Operation, FullyConnectedBiasGrad)
+{
+ {
+ // Shape: {2, 4}
+ std::vector<float> incoming_backward = {-1, 2, -3, 4, 5, -6, -7, 8};
+ // Shape: {4}
+ std::vector<float> expected_bias_backward = {4, -4, -10, 12};
+ std::vector<float> bias_backward(4);
+
+ nnfw::cker::train::FullyConnectedBiasGrad(
+ nnfw::cker::Shape{2, 4}, incoming_backward.data(),
+ nnfw::cker::Shape{static_cast<int>(bias_backward.size())}, bias_backward.data());
+
+ for (size_t i = 0; i < bias_backward.size(); ++i)
+ ASSERT_EQ(bias_backward[i], expected_bias_backward[i]);
+ }
+
+ {
+ // Shape: {3, 3}
+ std::vector<float> incoming_backward = {-1, 2, -3, 4, 5, -6, -7, 8, 9};
+ // Shape: {3}
+ std::vector<float> expected_bias_backward = {-4, 15, 0};
+ std::vector<float> bias_backward(3);
+
+ nnfw::cker::train::FullyConnectedBiasGrad(
+ nnfw::cker::Shape{3, 3}, incoming_backward.data(),
+ nnfw::cker::Shape{static_cast<int>(bias_backward.size())}, bias_backward.data());
+
+ for (size_t i = 0; i < bias_backward.size(); ++i)
+ ASSERT_EQ(bias_backward[i], expected_bias_backward[i]);
+ }
+
+ {
+ // Shape: {1, 2, 2, 3}
+ std::vector<float> incoming_backward = {-1, 2, -3, 4, 5, -6, -7, 8, 9, -10, -11, 12};
+ // Shape: {3}
+ std::vector<float> expected_bias_backward = {-14, 4, 12};
+ std::vector<float> bias_backward(3);
+
+ nnfw::cker::train::FullyConnectedBiasGrad(
+ nnfw::cker::Shape{1, 2, 2, 3}, incoming_backward.data(),
+ nnfw::cker::Shape{static_cast<int>(bias_backward.size())}, bias_backward.data());
+
+ for (size_t i = 0; i < bias_backward.size(); ++i)
+ ASSERT_EQ(bias_backward[i], expected_bias_backward[i]);
+ }
+}
+
+TEST(CKer_Operation, neg_FullyConnectedBiasGrad)
+{
+ {
+ // Unmatched shape
+ // Shape: {2, 4}
+ std::vector<float> incoming_backward = {-1, 2, -3, 4, 5, -6, -7, 8};
+ // Shape: {3}
+ std::vector<float> bias_backward(3);
+ EXPECT_ANY_THROW(nnfw::cker::train::FullyConnectedBiasGrad(
+ nnfw::cker::Shape{2, 4}, incoming_backward.data(),
+ nnfw::cker::Shape{static_cast<int>(bias_backward.size())},
+ bias_backward.data()););
+ }
+}
diff --git a/compute/cker/src/train/Loss.test.cc b/compute/cker/src/train/Loss.test.cc
new file mode 100644
index 000000000..98568f47a
--- /dev/null
+++ b/compute/cker/src/train/Loss.test.cc
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cker/train/operation/Loss.h>
+
+#include <gtest/gtest.h>
+#include <vector>
+
+TEST(CKer_Operation, LossMSE)
+{
+ {
+ // Shape: {1, 10} -> m_rows:10, m_cols:1
+ std::vector<int> y_pred = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+ std::vector<int> y_true = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ std::vector<int> output(1);
+ std::vector<int> expected = {1};
+
+ nnfw::cker::train::MSE(nnfw::cker::Shape{1, 10}, y_pred.data(), nnfw::cker::Shape{1, 10},
+ y_true.data(), nnfw::cker::Shape{1}, output.data());
+
+ EXPECT_EQ(output[0], expected[0]);
+ }
+
+ {
+ // Shape: {1, 10} -> m_rows:10, m_cols:1
+ std::vector<float> y_pred = {1., 2., 3., 4., 5., 6., 7., 8., 9., 10.};
+ std::vector<float> y_true = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};
+ std::vector<float> output(1);
+ std::vector<float> expected = {1.0};
+
+ nnfw::cker::train::MSE(nnfw::cker::Shape{1, 10}, y_pred.data(), nnfw::cker::Shape{1, 10},
+ y_true.data(), nnfw::cker::Shape{1}, output.data());
+
+ EXPECT_FLOAT_EQ(output[0], expected[0]);
+ }
+
+ {
+ // Shape: {2, 3} -> m_rows:3, m_cols:2
+ std::vector<float> y_pred = {27.2, 31.8, 51.9, 10.2, 34.2, 12.4};
+ std::vector<float> y_true = {31.3, 40.3, 29.7, 12.9, 25.8, 11.9};
+ std::vector<float> output(1);
+ std::vector<float> expected = {110.0};
+
+ nnfw::cker::train::MSE(nnfw::cker::Shape{2, 3}, y_pred.data(), nnfw::cker::Shape{2, 3},
+ y_true.data(), nnfw::cker::Shape{1}, output.data());
+
+ EXPECT_FLOAT_EQ(output[0], expected[0]);
+ }
+
+ {
+ // Shape: {2, 3, 4} -> m_rows:4, m_cols:6
+ std::vector<float> y_pred = {1., 2., 3., 4., 1., 2., 3., 4., 1., 2., 3., 4.,
+ 1., 2., 3., 4., 1., 2., 3., 4., 1., 2., 3., 4.};
+ std::vector<float> y_true = {1., 1., 1., 1., 2., 2., 2., 2., 3., 3., 3., 3.,
+ 1., 1., 1., 1., 2., 2., 2., 2., 3., 3., 3., 3.};
+ std::vector<float> output(1);
+ std::vector<float> expected = {2.1666667};
+
+ nnfw::cker::train::MSE(nnfw::cker::Shape{2, 3, 4}, y_pred.data(), nnfw::cker::Shape{2, 3, 4},
+ y_true.data(), nnfw::cker::Shape{1}, output.data());
+
+ EXPECT_FLOAT_EQ(output[0], expected[0]);
+ }
+}
+
+TEST(CKer_Operation, neg_LossMSE)
+{
+ {
+ // Invalid expected value
+ std::vector<float> y_pred = {1., 2., 3., 4., 5., 6., 7., 8., 9., 10.};
+ std::vector<float> y_true = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};
+ std::vector<float> output(1);
+ std::vector<float> expected = {-1.0};
+
+ nnfw::cker::train::MSE(nnfw::cker::Shape{2, 3, 4}, y_pred.data(), nnfw::cker::Shape{2, 3, 4},
+ y_true.data(), nnfw::cker::Shape{1}, output.data());
+
+ EXPECT_NE(output[0], expected[0]);
+ }
+
+ {
+ // Invalid output shape
+ std::vector<float> y_pred = {1., 2., 3., 4., 5., 6., 7., 8., 9., 10.};
+ std::vector<float> y_true = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};
+ std::vector<float> output(3);
+ std::vector<float> expected = {1.0};
+
+ EXPECT_ANY_THROW(nnfw::cker::train::MSE(nnfw::cker::Shape{2, 3, 4}, y_pred.data(),
+ nnfw::cker::Shape{2, 3, 4}, y_true.data(),
+ nnfw::cker::Shape{3}, output.data()));
+ }
+
+ {
+ // Different y_pread and y_true shape
+ std::vector<float> y_pred = {1., 2., 3., 4., 5., 6., 7., 8., 9., 10.};
+ std::vector<float> y_true = {0., 1., 2., 3., 4., 5.};
+ std::vector<float> output(1);
+ std::vector<float> expected = {1.0};
+
+ EXPECT_ANY_THROW(nnfw::cker::train::MSE(nnfw::cker::Shape{2, 3, 4}, y_pred.data(),
+ nnfw::cker::Shape{2, 3}, y_true.data(),
+ nnfw::cker::Shape{1}, output.data()));
+ }
+}
+
+TEST(CKer_Operation, LossMSEGrad)
+{
+ {
+ // Shape: {1, 10} -> m_rows:10, m_cols:1
+ std::vector<int> y_pred = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+ std::vector<int> y_true = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ std::vector<int> deriv_y_pred(10);
+ std::vector<int> expected = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+ nnfw::cker::train::MSEGrad(nnfw::cker::Shape{1, 10}, y_pred.data(), nnfw::cker::Shape{1, 10},
+ y_true.data(), nnfw::cker::Shape{1, 10}, deriv_y_pred.data());
+
+ for (size_t i = 0; i < deriv_y_pred.size(); ++i)
+ EXPECT_EQ(deriv_y_pred[i], expected[i]);
+ }
+
+ {
+ // Shape: {1, 10} -> m_rows:10, m_cols:1
+ std::vector<float> y_pred = {1., 2., 3., 4., 5., 6., 7., 8., 9., 10.};
+ std::vector<float> y_true = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};
+ std::vector<float> deriv_y_pred(10);
+ std::vector<float> expected = {0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2};
+
+ nnfw::cker::train::MSEGrad(nnfw::cker::Shape{1, 10}, y_pred.data(), nnfw::cker::Shape{1, 10},
+ y_true.data(), nnfw::cker::Shape{1, 10}, deriv_y_pred.data());
+
+ for (size_t i = 0; i < deriv_y_pred.size(); ++i)
+ EXPECT_FLOAT_EQ(deriv_y_pred[i], expected[i]);
+ }
+
+ {
+ // Shape: {2, 3} -> m_rows:3, m_cols:2
+ std::vector<float> y_pred = {27.2, 31.8, 51.9, 10.2, 34.2, 12.4};
+ std::vector<float> y_true = {31.3, 40.3, 29.7, 12.9, 25.8, 11.9};
+ std::vector<float> deriv_y_pred(6);
+ std::vector<float> expected = {-1.3666667, -2.8333333, 7.4, -0.9, 2.8, 0.1666667};
+
+ nnfw::cker::train::MSEGrad(nnfw::cker::Shape{2, 3}, y_pred.data(), nnfw::cker::Shape{2, 3},
+ y_true.data(), nnfw::cker::Shape{2, 3}, deriv_y_pred.data());
+
+ for (size_t i = 0; i < deriv_y_pred.size(); ++i)
+ EXPECT_FLOAT_EQ(deriv_y_pred[i], expected[i]);
+ }
+}
+
+TEST(CKer_Operation, neg_LossMSEGrad)
+{
+ {
+ // Invalid expected value
+ std::vector<float> y_pred = {27.2, 31.8, 51.9, 10.2, 34.2, 12.4};
+ std::vector<float> y_true = {31.3, 40.3, 29.7, 12.9, 25.8, 11.9};
+ std::vector<float> deriv_y_pred(6);
+ std::vector<float> expected = {1., 1., 1., 1., 1., 1.};
+
+ nnfw::cker::train::MSEGrad(nnfw::cker::Shape{2, 3}, y_pred.data(), nnfw::cker::Shape{2, 3},
+ y_true.data(), nnfw::cker::Shape{2, 3}, deriv_y_pred.data());
+
+ for (size_t i = 0; i < deriv_y_pred.size(); ++i)
+ EXPECT_NE(deriv_y_pred[i], expected[i]);
+ }
+
+ {
+ // Different y_pred and y_true shape
+ std::vector<float> y_pred = {1., 2., 3., 4., 5., 6., 7., 8., 9., 10.};
+ std::vector<float> y_true = {0., 1., 2., 3., 4., 5.};
+ std::vector<float> deriv_y_pred(10);
+
+ EXPECT_ANY_THROW(nnfw::cker::train::MSEGrad(nnfw::cker::Shape{1, 10}, y_pred.data(),
+ nnfw::cker::Shape{2, 3}, y_true.data(),
+ nnfw::cker::Shape{1, 10}, deriv_y_pred.data()));
+ }
+
+ {
+ // Different y_pred and deriv_y_pred shape
+ std::vector<float> y_pred = {1., 2., 3., 4., 5., 6., 7., 8., 9., 10.};
+ std::vector<float> y_true = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};
+ std::vector<float> deriv_y_pred(6);
+
+ EXPECT_ANY_THROW(nnfw::cker::train::MSEGrad(nnfw::cker::Shape{1, 10}, y_pred.data(),
+ nnfw::cker::Shape{1, 10}, y_true.data(),
+ nnfw::cker::Shape{2, 3}, deriv_y_pred.data()));
+ }
+}
diff --git a/compute/cker/src/train/Relu.test.cc b/compute/cker/src/train/Relu.test.cc
new file mode 100644
index 000000000..d94411038
--- /dev/null
+++ b/compute/cker/src/train/Relu.test.cc
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cker/operation/ReLU.h>
+#include <cker/train/operation/ReLU.h>
+
+#include <gtest/gtest.h>
+#include <vector>
+
+namespace
+{
+
+template <typename T> class ReluOpVerifier
+{
+public:
+ ReluOpVerifier(const std::vector<T> &input, const std::vector<T> &expected_output,
+ const std::vector<T> &backprop_output,
+ const std::vector<T> &expected_backprop_input)
+ : _input{input}, _expected_output{expected_output}, _backprop_output{backprop_output},
+ _expected_backprop_input{expected_backprop_input}
+ {
+ EXPECT_TRUE(input.size() == expected_output.size());
+ _output.resize(_expected_output.size());
+ _backprop_input.resize(_expected_backprop_input.size());
+ }
+
+public:
+ void verifyExpected()
+ {
+ nnfw::cker::ReLU(nnfw::cker::Shape{static_cast<int>(_input.size())}, _input.data(),
+ nnfw::cker::Shape{static_cast<int>(_output.size())}, _output.data());
+
+ for (size_t i = 0; i < _output.size(); ++i)
+ ASSERT_EQ(_output[i], _expected_output[i]);
+
+ if (_backprop_output.size() > 0)
+ {
+ nnfw::cker::train::ReLUGrad(
+ nnfw::cker::Shape{static_cast<int>(_output.size())}, _output.data(),
+ nnfw::cker::Shape{static_cast<int>(_backprop_output.size())}, _backprop_output.data(),
+ nnfw::cker::Shape{static_cast<int>(_backprop_input.size())}, _backprop_input.data());
+
+ for (size_t i = 0; i < _backprop_input.size(); ++i)
+ ASSERT_EQ(_backprop_input[i], _expected_backprop_input[i]);
+ }
+ }
+
+private:
+ std::vector<T> _input;
+ std::vector<T> _output;
+ std::vector<T> _expected_output;
+ std::vector<T> _backprop_output;
+ std::vector<T> _backprop_input;
+ std::vector<T> _expected_backprop_input;
+};
+
+} // namespace
+
+TEST(CKer_Operation, ReLU)
+{
+ {
+ std::vector<float> input_forward = {-1, 2, 3, -4};
+ std::vector<float> expected_forward = {0, 2, 3, 0};
+ std::vector<float> incoming_backward = {-5, 6, -7, 8};
+ std::vector<float> expected_backward = {0, 6, -7, 0};
+ ReluOpVerifier<float> verifier{input_forward, expected_forward, incoming_backward,
+ expected_backward};
+ verifier.verifyExpected();
+ }
+
+ {
+ std::vector<float> input_forward = {0, -1, 2, 3, -4, 5, 6, -7};
+ std::vector<float> expected_forward = {0, 0, 2, 3, 0, 5, 6, 0};
+ std::vector<float> incoming_backward = {8, -9, 10, 11, -12, -13, 14, -15};
+ std::vector<float> expected_backward = {0, 0, 10, 11, 0, -13, 14, 0};
+ ReluOpVerifier<float> verifier{input_forward, expected_forward, incoming_backward,
+ expected_backward};
+ verifier.verifyExpected();
+ }
+}
+
+TEST(CKer_Operation, neg_ReLU)
+{
+ {
+ // Unmatched shape
+ std::vector<float> input_forward = {0, -1, 2, 3, -4};
+ std::vector<float> expected_forward = {0, 0, 2, 3, 0};
+ std::vector<float> incoming_backward = {-5, 6, -7, 8};
+ std::vector<float> expected_backward = {0, 6, -7, 0};
+ ReluOpVerifier<float> verifier{input_forward, expected_forward, incoming_backward,
+ expected_backward};
+ EXPECT_ANY_THROW(verifier.verifyExpected());
+ }
+}
diff --git a/compute/ruy/include/ruy/Shape.h b/compute/ruy/include/ruy/Shape.h
index 981c5b4de..151a67377 100644
--- a/compute/ruy/include/ruy/Shape.h
+++ b/compute/ruy/include/ruy/Shape.h
@@ -156,7 +156,7 @@ public:
const int dimensions_count = std::distance(src_iterable.begin(), src_iterable.end());
Resize(dimensions_count);
int32_t *data = DimsData();
- for (auto it : src_iterable)
+ for (auto &&it : src_iterable)
{
*data = it;
++data;
diff --git a/docs/conf.py b/docs/conf.py
index c33e103e8..50256719a 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -21,7 +21,7 @@ copyright = '2020, Samsung Research & contributors'
author = 'Samsung Research & contributors'
# The full version, including alpha/beta/rc tags
-release = '1.22.1'
+release = '1.25.0'
# -- General configuration ---------------------------------------------------
diff --git a/docs/howto/how-to-build-compiler.md b/docs/howto/how-to-build-compiler.md
index 7a1fa1cc7..3a9638677 100644
--- a/docs/howto/how-to-build-compiler.md
+++ b/docs/howto/how-to-build-compiler.md
@@ -45,9 +45,6 @@ pylint \
python3 \
python3-pip \
python3-venv \
-python3.8 \
-python3.8-dev \
-python3.8-venv \
scons \
software-properties-common \
unzip \
@@ -62,6 +59,16 @@ $ sudo mv *.a /usr/lib
$ pip install yapf==0.22.0 numpy
```
+Additional install python3.8 if you are using Ubuntu 18.04.
+```
+$ sudo apt-get install \
+python3.8 \
+python3.8-dev \
+python3.8-venv
+```
+
+If you get `Unable to locate package clang-format-8` then just use `clang-format`.
+
## Build for Ubuntu
In a typical linux development environment, including Ubuntu, you can build the compiler with a
diff --git a/docs/howto/how-to-build-runtime.md b/docs/howto/how-to-build-runtime.md
index f83ec5bc4..f4d7b56e0 100644
--- a/docs/howto/how-to-build-runtime.md
+++ b/docs/howto/how-to-build-runtime.md
@@ -1,11 +1,12 @@
# How to Build Runtime
-This document is based on the system where Ubuntu Desktop Linux 18.04 LTS is installed with default settings, and can be applied in other environments without much difference. For reference, the development of our project started in the Ubuntu Desktop Linux 16.04 LTS environment.
+This document is based on the system where Ubuntu Desktop Linux 20.04 LTS is installed with default settings, and can be applied in other environments without much difference. For reference, the development of our project started in the Ubuntu Desktop Linux 16.04 LTS environment.
## Build requirements
If you are going to build this project, the following modules must be installed on your system:
+- C & C++ compiler
- CMake
- Boost C++ libraries
@@ -15,9 +16,9 @@ In the Ubuntu, you can easily install it with the following command.
$ sudo apt-get install cmake libboost-all-dev
```
-If your linux system does not have the basic development configuration, you will need to install more packages. A list of all packages needed to configure the development environment can be found in https://github.com/Samsung/ONE/blob/master/infra/docker/bionic/Dockerfile.
+If your linux system does not have the basic development configuration, you will need to install more packages. A list of all packages needed to configure the development environment can be found in https://github.com/Samsung/ONE/blob/master/infra/docker/focal/Dockerfile.
-Here is a summary of it
+Here is a summary of it for runtime and related tools
```
$ sudo apt install \
@@ -29,30 +30,16 @@ git \
graphviz \
hdf5-tools \
lcov \
-libatlas-base-dev \
libboost-all-dev \
-libgflags-dev \
-libgoogle-glog-dev \
-libgtest-dev \
libhdf5-dev \
-libprotobuf-dev \
-protobuf-compiler \
-pylint \
python3 \
python3-pip \
-python3-venv \
scons \
software-properties-common \
unzip \
wget
-$ mkdir /tmp/gtest
-$ cd /tmp/gtest
-$ cmake /usr/src/gtest
-$ make
-$ sudo mv *.a /usr/lib
-
-$ pip install yapf==0.22.0 numpy
+$ pip3 install yapf==0.22.0 numpy
```
@@ -63,10 +50,18 @@ In a typical linux development environment, including Ubuntu, you can build the
```
$ git clone https://github.com/Samsung/ONE.git one
$ cd one
-$ make -f Makefile.template install
+$ ./nnfw configure
+$ ./nnfw build
+$ ./nnfw install
+```
+
+For easy build process, we provides `Makefile.template` makefile.
+
+```
+$ make -f Makefile.template
```
-Unfortunately, the debug build on the x86_64 architecture currently has an error. To solve the problem, you must use gcc version 9 or higher. Another workaround is to do a release build rather than a debug build. This is not a suitable method for debugging during development, but it is enough to check the function of the runtime. To release build the runtime, add the environment variable `BUILD_TYPE=release` to the build command as follows.
+To release build the runtime, add the environment variable `BUILD_TYPE=release` to the build command as follows.
```
$ export BUILD_TYPE=release
@@ -94,77 +89,74 @@ $ tree -L 2 ./Product
$ tree -L 3 ./Product/out
./Product/out
├── bin
-│   ├── onert_run
-│   ├── tflite_comparator
-│   └── tflite_run
+│ ├── onert_run
+│ ├── tflite_comparator
+│ └── tflite_run
├── include
-│   ├── nnfw
-│   │   ├── NeuralNetworksEx.h
-│   │   ├── NeuralNetworksExtensions.h
-│   │   ├── NeuralNetworks.h
-│   │   ├── nnfw_experimental.h
-│   │   └── nnfw.h
-│   └── onert
-│   ├── backend
-│   ├── compiler
-│   ├── exec
-│   ├── ir
-│   └── util
+│ ├── nnfw
+│ │ ├── NeuralNetworksEx.h
+│ │ ├── NeuralNetworksExtensions.h
+│ │ ├── NeuralNetworks.h
+│ │ ├── nnfw_experimental.h
+│ │ └── nnfw.h
+│ └── onert
+│ ├── backend
+│ ├── compiler
+│ ├── exec
+│ ├── ir
+│ └── util
├── lib
-│   ├── libbackend_cpu.so
-│   ├── libbackend_ruy.so
-│   ├── libneuralnetworks.so
-│   ├── libnnfw-dev.so
-│   └── libonert_core.so
+│ ├── libbackend_cpu.so
+│ ├── libbackend_ruy.so
+│ ├── libneuralnetworks.so
+│ ├── libnnfw-dev.so
+│ └── libonert_core.so
├── nnapi-gtest
-│   ├── nnapi_gtest
-│   ├── nnapi_gtest.skip
-│   ├── nnapi_gtest.skip.noarch.interp
-│   └── nnapi_gtest.skip.x86_64-linux.cpu
+│ ├── nnapi_gtest
+│ ├── nnapi_gtest.skip
+│ └── nnapi_gtest.skip.x86_64-linux.cpu
├── test
-│   ├── command
-│   │   ├── nnpkg-test
-│   │   ├── prepare-model
-│   │   ├── unittest
-│   │   └── verify-tflite
-│   ├── FillFrom_runner
-│   ├── list
-│   │   ├── benchmark_nnpkg_model_list.txt
-│   │   ├── nnpkg_test_list.armv7l-linux.acl_cl
-│   │   ├── nnpkg_test_list.armv7l-linux.acl_neon
-│   │   ├── nnpkg_test_list.armv7l-linux.cpu
-│   │   ├── nnpkg_test_list.noarch.interp
-│   │   ├── tflite_comparator.aarch64.acl_cl.list
-│   │   ├── tflite_comparator.aarch64.acl_neon.list
-│   │   ├── tflite_comparator.aarch64.cpu.list
-│   │   ├── tflite_comparator.armv7l.acl_cl.list
-│   │   ├── tflite_comparator.armv7l.acl_neon.list
-│   │   ├── tflite_comparator.armv7l.cpu.list
-│   │   ├── tflite_comparator.noarch.interp.list
-│   │   └── tflite_comparator.x86_64.cpu.list
-│   ├── models
-│   │   ├── run_test.sh
-│   │   └── tflite
-│   ├── nnpkgs
-│   │   └── FillFrom
-│   └── onert-test
+│ ├── command
+│ │ ├── nnpkg-test
+│ │ ├── prepare-model
+│ │ ├── unittest
+│ │ └── verify-tflite
+│ ├── FillFrom_runner
+│ ├── list
+│ │ ├── benchmark_nnpkg_model_list.txt
+│ │ ├── nnpkg_test_list.armv7l-linux.acl_cl
+│ │ ├── nnpkg_test_list.armv7l-linux.acl_neon
+│ │ ├── nnpkg_test_list.armv7l-linux.cpu
+│ │ ├── tflite_comparator.aarch64.acl_cl.list
+│ │ ├── tflite_comparator.aarch64.acl_neon.list
+│ │ ├── tflite_comparator.aarch64.cpu.list
+│ │ ├── tflite_comparator.armv7l.acl_cl.list
+│ │ ├── tflite_comparator.armv7l.acl_neon.list
+│ │ ├── tflite_comparator.armv7l.cpu.list
+│ │ └── tflite_comparator.x86_64.cpu.list
+│ ├── models
+│ │ ├── run_test.sh
+│ │ └── tflite
+│ ├── nnpkgs
+│ │ └── FillFrom
+│ └── onert-test
└── unittest
├── ndarray_test
├── nnfw_api_gtest
├── nnfw_api_gtest_models
- │   ├── add
- │   ├── add_invalid_manifest
- │   ├── add_no_manifest
- │   ├── if_dynamic
- │   ├── mobilenet_v1_1.0_224
- │   └── while_dynamic
+ │ ├── add
+ │ ├── add_invalid_manifest
+ │ ├── add_no_manifest
+ │ ├── if_dynamic
+ │ ├── mobilenet_v1_1.0_224
+ │ └── while_dynamic
├── nnfw_lib_misc_test
├── test_cker
├── test_onert_core
├── test_onert_frontend_nnapi
└── tflite_test
-26 directories, 46 files
+26 directories, 42 files
```
@@ -184,7 +176,7 @@ inception_v3.tflite
The result of running the inception_v3 model using runtime is as follows. Please consider that this is a test that simply checks execution latency without considering the accuracy of the model.
```
-$ ./Product/out/bin/onert_run --modelfile ./inception_v3.tflite
+$ ./Product/out/bin/onert_run ./inception_v3.tflite
Model Filename ./inception_v3.tflite
===================================
MODEL_LOAD takes 1.108 ms
diff --git a/docs/howto/how-to-cross-build-runtime-for-arm.md b/docs/howto/how-to-cross-build-runtime-for-arm.md
index 91481a9d7..2db4d564a 100644
--- a/docs/howto/how-to-cross-build-runtime-for-arm.md
+++ b/docs/howto/how-to-cross-build-runtime-for-arm.md
@@ -13,26 +13,26 @@ Use `install_rootfs.sh` script to prepare Root File System. You should have `sud
```
$ sudo ./tools/cross/install_rootfs.sh arm
```
-- supports `arm`(default) and `aarch` architecutre for now
-- supports `bionic`(default), and `focal` release
+- supports `arm`(default) and `aarch64` architecutre for now
+- supports `focal`(default), `bionic`, and `jammy` release
To see the options,
```
$ ./tools/cross/install_rootfs.sh -h
```
-RootFS will be prepared at `tools/cross/rootfs/arm` folder.
+RootFS will be prepared at `tools/cross/rootfs/arm` or `tools/cross/rootfs/aarch64` folder.
***\* CAUTION: The OS version of rootfs must match the OS version of execution target device. On the other hand, you need to match the Ubuntu version of the development PC with the Ubuntu version of rootfs to be used for cross-build. Otherwise, unexpected build errors may occur.***
-If you are using Ubuntu 18.04 LTS, select `bionic`, if you are using Ubuntu 20.04 LTS, select `focal`. You can check your Ubuntu code name in the following way.
+If you are using Ubuntu 20.04 LTS, select `focal`, if you are using Ubuntu 22.04 LTS, select `jammy`. You can check your Ubuntu code name in the following way.
```
$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
-DISTRIB_RELEASE=18.04
-DISTRIB_CODENAME=bionic
-DISTRIB_DESCRIPTION="Ubuntu 18.04.4 LTS"
+DISTRIB_RELEASE=22.04
+DISTRIB_CODENAME=jammy
+DISTRIB_DESCRIPTION="Ubuntu 22.04.3 LTS"
```
If a build error occurs because the version of the development system and the target system do not match, and if you can't replace your development system for any reason, you can consider [cross-build using the docker image](how-to-build-runtime-using-prebuilt-docker-image.md).
@@ -61,29 +61,32 @@ for `http`, `https` and `ftp` protocol.
## Install ARM Cross Toolchain
-We recommend you have g++ >= 6 installed on your system because NN generated tests require it.
+We recommend you have g++ >= 6.1 installed on your system because NN generated tests require it (c++14).
-### Ubuntu 18.04 LTS
+### Ubuntu 20.04 LTS
-On Ubuntu 18.04 LTS, you can install using `apt-get`.
+On Ubuntu 20.04 LTS, you can install using `apt-get`.
-Choose g++ version whatever you prefer: 7 (default), 6 or 8.
+Choose g++ version whatever you prefer: 9 (default) or 10. We are officially testing on default g++ version,
+so we don't confirm build on different version.
```
-$ sudo apt-get install g++-{6,7,8}-arm-linux-gnueabihf
+$ sudo apt-get install g++-{9,10}-arm-linux-gnueabihf
```
-If you select specific version, update symbolic link for build toolchain
+If you select specific version, update symbolic link for build toolchain.
+
+Otherwise, you should set your custom cmake crossbuild toolchain. You can find cmake toolchain files in `infra/nnfw/cmake/buildtool/cross/`.
```
-$ update-alternatives --install /usr/bin/arm-linux-gnueabihf-gcc arm-linux-gnueabihf-gcc /usr/bin/arm-linux-gnueabihf-gcc-8 80 \
- --slave /usr/bin/arm-linux-gnueabihf-g++ arm-linux-gnueabihf-g++ /usr/bin/arm-linux-gnueabihf-g++-8 \
- --slave /usr/bin/arm-linux-gnueabihf-gcov arm-linux-gnueabihf-gcov /usr/bin/arm-linux-gnueabihf-gcov-8
+$ update-alternatives --install /usr/bin/arm-linux-gnueabihf-gcc arm-linux-gnueabihf-gcc /usr/bin/arm-linux-gnueabihf-gcc-10 80 \
+ --slave /usr/bin/arm-linux-gnueabihf-g++ arm-linux-gnueabihf-g++ /usr/bin/arm-linux-gnueabihf-g++-10 \
+ --slave /usr/bin/arm-linux-gnueabihf-gcov arm-linux-gnueabihf-gcov /usr/bin/arm-linux-gnueabihf-gcov-10
```
-### Ubuntu 20.04 LTS
+### Ubuntu 22.04 LTS
-Same with Ubuntu 18.04 LTS. (except g++ version)
+Same with Ubuntu 20.04 LTS. (except g++ version)
## Build and install ARM Compute Library
@@ -95,18 +98,18 @@ To build ACL, you need to install scons
$ sudo apt-get install scons
```
-ACL will be automatically installed in `externals/acl` when you build runtime without any changes.
+ACL source will be automatically installed in `externals/ARMCOMPUTE` when you build runtime without any changes.
You can check ACL source information in `infra/cmake/packages/ARMComputeSourceConfig.cmake`
-## Cross build for ARM
+## Cross build for ARM by using Makefile.template
Give `TARGET_ARCH` variable to set the target architecture.
If you used `ROOTFS_DIR` to prepare in alternative folder, you should also give this to makefile.
```
-$ CROSS_BUILD=1 TARGET_ARCH=armv7l make
+$ CROSS_BUILD=1 TARGET_ARCH=armv7l make -f Makefile.template
# If ROOTFS_DIR is in alternative folder
$ ROOTFS_DIR=/path/to/your/rootfs/arm \
@@ -121,15 +124,23 @@ normal build and cross build as follows.
```
$ export ROOTFS_DIR=xxx
...
-$ make # do normal build
-$ TARGET_ARCH=armv7l make # do cross build
+$ make -f Makefile.template # do normal build
+$ TARGET_ARCH=armv7l make -f Makefile.template # do cross build
```
+Makefile.template will pass crossbuild toolchain setting to cmake automatically by parsing variables.
+
### Run test
-To run and test the cross-compiled runtime, you need to copy the compiled output to the target device of the architecture in which it is executable.
+To run and test the cross-compiled runtime, you need to install library packages and copy the compiled output to the target device of the architecture in which it is executable.
+
+1. Install hdf5 and boost library package
+
+```
+$ sudo apt install libhdf5-dev libboost-system-dev libboost-program-options-dev
+```
-1. Copy all artifacts under the `./Product` folder to the target device, Odroid-XU4 for example, as a whole.
+2. Copy all artifacts under the `./Product/armv7l-linux.<BUILD_TYPE>` folder to the target device, Odroid-XU4 for example, as a whole.
```
$ ssh odroid mkdir -p one/Product
@@ -144,7 +155,7 @@ test-driver.sh
...
```
-2. Log in to the target device, go to the copied path, and reestore the symbolic link settings of the `Product` directory.
+3. Log in to the target device, go to the copied path, and reestore the symbolic link settings of the `Product` directory.
```
$ ssh odroid
diff --git a/docs/release/1.23/index.rst b/docs/release/1.23/index.rst
new file mode 100644
index 000000000..ae29d5226
--- /dev/null
+++ b/docs/release/1.23/index.rst
@@ -0,0 +1,13 @@
+.. ONE documentation master file, created by
+ sphinx-quickstart on Thu May 18 19:07:17 2023.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+1.23
+====
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Contents:
+
+ ./release-note-1.23.0.md
diff --git a/docs/release/1.23/release-note-1.23.0.md b/docs/release/1.23/release-note-1.23.0.md
new file mode 100644
index 000000000..b5a3d1b9b
--- /dev/null
+++ b/docs/release/1.23/release-note-1.23.0.md
@@ -0,0 +1,8 @@
+# Release Note 1.23.0
+
+## ONE Compiler
+
+- Support more Op(s): GeLU
+- Support more option(s): `--fuse-gelu`
+- Support multiple backends compilation with a single configuration file
+- Upgrade Circle schema to 0.5
diff --git a/docs/release/1.24/index.rst b/docs/release/1.24/index.rst
new file mode 100644
index 000000000..fa1698820
--- /dev/null
+++ b/docs/release/1.24/index.rst
@@ -0,0 +1,13 @@
+.. ONE documentation master file, created by
+ sphinx-quickstart on Thu Jul 18 14:08:15 2023.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+1.24
+====
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Contents:
+
+ ./release-note-1.24.0.md
diff --git a/docs/release/1.24/release-note-1.24.0.md b/docs/release/1.24/release-note-1.24.0.md
new file mode 100644
index 000000000..9020da8aa
--- /dev/null
+++ b/docs/release/1.24/release-note-1.24.0.md
@@ -0,0 +1,9 @@
+# Release Note 1.24.0
+
+## ONE Compiler
+
+- Introduce _one-import-onnx_ extension interface
+- _onecc_ supports profiling of multiple backends with a single cfg file
+- Enable more Quantize operator: FloorMod, Squeeze
+- _visq_ supports multi-out nodes
+- _onecc_ introduces `dynamic_batch_to_single_batch option` option.
diff --git a/docs/release/1.25/index.rst b/docs/release/1.25/index.rst
new file mode 100644
index 000000000..1965b42e8
--- /dev/null
+++ b/docs/release/1.25/index.rst
@@ -0,0 +1,13 @@
+.. ONE documentation master file, created by
+ sphinx-quickstart on Wed Sep 06 12:18:12 2022.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+1.25
+====
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Contents:
+
+ ./release-note-1.25.0.md
diff --git a/docs/release/1.25/release-note_1.25.0.md b/docs/release/1.25/release-note_1.25.0.md
new file mode 100644
index 000000000..3d62c6bde
--- /dev/null
+++ b/docs/release/1.25/release-note_1.25.0.md
@@ -0,0 +1,17 @@
+# Release Note 1.25.0
+
+## ONE Runtime
+
+- Support ubuntu 20.04
+
+### CPU Backend Operation
+- CPU backend supports per-channel hybrid quantization of int8 type weight and float activation. (TFLite's dynamic range quantization)
+
+### On-device Quantization
+- _onert_ supports new experimental API for on-device quantization.
+- As the 1st step, _onert_ supports per-channel hybrid quantization of int8/int16 type weight and float activation.
+- API requires file path to export quantized model.
+
+### Minmax Recorder
+- _onert_` support minmax recording of each layer as experimental feature. It is not supported by API yet.
+- Output file format is HDF5. (File format may change later).
diff --git a/docs/release/onert-micro/0.1/release-note-0.1.0.md b/docs/release/onert-micro/0.1/release-note-0.1.0.md
new file mode 100644
index 000000000..5a4692b4f
--- /dev/null
+++ b/docs/release/onert-micro/0.1/release-note-0.1.0.md
@@ -0,0 +1,72 @@
+## Release Notes for onert-micro 0.1.0
+
+_onert-micro_ is tiny runtime specialized for running NN model in MCU boards. Note that onert-micro is under active development and is subject to change.
+
+### Supported operations
+
+For MCU board, we support 22 operations as follows :
+
+ ADD, FULLY_CONNECTED, CONV_2D, LOGISTIC ,GATHER, EXPAND_DIMS, PACK, RESHAPE, REDUCE_PROD, LESS, MUL, MAX_POOL_2D, CONCATENATION, SHAPE, SLICE, SUB, SPLIT, STRIDED_SLICE, TANH, SOFTMAX, WHILE, UNIDIRECTIONAL_SEQUENCE_LSTM
+
+### RNN Model
+
+#### LSTM
+
+onert-micro supports Keras model with LSTM operations. But, it should be converted to UNIDIRECTIONAL_SEQUENCE_LSTM operation in circle format.
+
+#### GRU
+
+onert-micro supports model with GRU Operations, which is converted from Keras Model. Please refer to https://github.com/Samsung/ONE/issues/10465 to see GRU operation supported by onert-micro.
+
+### Benchmark
+
+onert-micro shows better performance than tflite-micro especially in memory consumption, binary size.
+
+The measurement is done on TizenRT running reference models on the development board with the following spec :
+
+- 32-bit Arm Cortex-M33 200MHz
+- 4MB RAM, 8MB Flash
+
+Commit for measurement :
+- tflite-micro commit: https://github.com/tensorflow/tflite-micro/commit/4e62ea7b821c1e6af004912132395fb81922ea8d
+
+- onert-micro commit: https://github.com/Samsung/ONE/commit/c763867500fe3d80bfd1ef834990d34a81640d17
+#### L model
+
+| Params | Tflite micro | Onert-micro |
+|-----------------------------------|---------------|-------------|
+| Execution time(us)* | **2 912 700** | 2 953 000 |
+| RAM consumption(bytes) | 126 800 | **93 376** |
+| Binary file size overhead (bytes) | 57 676 | **32 248** |
+
+
+#### T1 model
+
+Params | Tflite micro | Onert-micro |
+--- | --- | ---
+Execution time(us)* | **1 340** | 1 510 |
+RAM consumption(bytes) | 1 640 | **1 152** |
+Binary file size overhead (bytes) | 35 040 | **19 432** |
+
+#### T2 model
+
+Params | Tflite micro** | Onert-micro |
+--- | --- | ---
+Execution time(us)* | N/A | 5 090 |
+RAM consumption(bytes) | N/A | 3 360 |
+Binary file size overhead (bytes) | N/A | 30 488 |
+
+#### Model with GRU operations
+
+- model link : https://github.com/Samsung/ONE/files/8368702/gru.zip
+
+Params | Tflite micro** | Onert-micro |
+--- | --- | ---
+Execution time(us)* | N/A | 335 000 |
+RAM consumption(bytes) | N/A | 14 816 |
+Binary file size overhead (bytes) | N/A | 43 444 |
+
+
+(*) Average for 100 inferences
+(**) Tflite-micro has not launched this model
+
diff --git a/docs/release/onert-micro/1.0/release-note-1.0.0.md b/docs/release/onert-micro/1.0/release-note-1.0.0.md
new file mode 100644
index 000000000..a18d55724
--- /dev/null
+++ b/docs/release/onert-micro/1.0/release-note-1.0.0.md
@@ -0,0 +1,12 @@
+## Release Notes for onert-micro 1.0
+
+### Supported operations
+
+More operations are supported as follows:
+
+- AveragePool2D, Elu, Exp, Abs, Neg, Div, AddN, Relu, Relu6, Leak_Relu, Pad, PadV2, ArgMin, ArgMax, Resize_Bilinear, LogicalAnd, LogicalOr, Equal, NotEqual, Greater, GreaterEqual, LessEqual
+
+### Etc
+
+- Address sanitizer build option(ENABLE_SANITIZER) is added
+- Fix buffer overflow in static analyzer's defect
diff --git a/infra/cmake/packages/AbseilSourceConfig.cmake b/infra/cmake/packages/AbseilSourceConfig.cmake
index 0297c08bc..8d0c7798f 100644
--- a/infra/cmake/packages/AbseilSourceConfig.cmake
+++ b/infra/cmake/packages/AbseilSourceConfig.cmake
@@ -7,13 +7,13 @@ function(_AbseilSource_import)
nnas_include(ExternalSourceTools)
nnas_include(OptionTools)
- # NOTE TensorFlow 2.9 downloads abseil 20211102.0
+ # NOTE GCC 13 requires abseil 20230125.3
envoption(EXTERNAL_DOWNLOAD_SERVER "https://github.com")
- envoption(ABSEIL_URL ${EXTERNAL_DOWNLOAD_SERVER}/abseil/abseil-cpp/archive/20211102.0.tar.gz)
+ envoption(ABSEIL_URL ${EXTERNAL_DOWNLOAD_SERVER}/abseil/abseil-cpp/archive/20230125.3.tar.gz)
ExternalSource_Download(ABSEIL
DIRNAME ABSEIL
URL ${ABSEIL_URL}
- CHECKSUM MD5=bdca561519192543378b7cade101ec43)
+ CHECKSUM MD5=9b6dae642c4bd92f007ab2c148bc0498)
set(AbseilSource_DIR ${ABSEIL_SOURCE_DIR} PARENT_SCOPE)
set(AbseilSource_FOUND TRUE PARENT_SCOPE)
diff --git a/infra/cmake/packages/CMSIS-NN-4.1.0/CMSIS-NNConfig.cmake b/infra/cmake/packages/CMSIS-NN-4.1.0/CMSIS-NNConfig.cmake
new file mode 100644
index 000000000..06106dc60
--- /dev/null
+++ b/infra/cmake/packages/CMSIS-NN-4.1.0/CMSIS-NNConfig.cmake
@@ -0,0 +1,14 @@
+function(_CMSIS_NN_import)
+ nnas_include(ExternalSourceTools)
+ nnas_include(OptionTools)
+
+ envoption(EXTERNAL_DOWNLOAD_SERVER "https://github.com")
+ envoption(CMSIS_NN_4_1_0_URL ${EXTERNAL_DOWNLOAD_SERVER}/ARM-software/CMSIS-NN/archive/refs/tags/v4.1.0.tar.gz)
+
+ ExternalSource_Download(CMSIS_NN DIRNAME CMSIS-NN-4.1.0 ${CMSIS_NN_4_1_0_URL})
+
+ set(CMSIS_NNSource_DIR ${CMSIS_NN_SOURCE_DIR} PARENT_SCOPE)
+ set(CMSIS_NNSource_FOUND TRUE PARENT_SCOPE)
+endfunction(_CMSIS_NN_import)
+
+_CMSIS_NN_import()
diff --git a/infra/cmake/packages/CMSIS-NN-4.1.0/CMSIS-NNConfigVersion.cmake b/infra/cmake/packages/CMSIS-NN-4.1.0/CMSIS-NNConfigVersion.cmake
new file mode 100644
index 000000000..5296e197d
--- /dev/null
+++ b/infra/cmake/packages/CMSIS-NN-4.1.0/CMSIS-NNConfigVersion.cmake
@@ -0,0 +1,10 @@
+set(PACKAGE_VERSION "4.1.0")
+set(PACKAGE_VERSION_EXACT FALSE)
+set(PACKAGE_VERSION_COMPATIBLE FALSE)
+set(PACKAGE_VERSION_UNSUITABLE TRUE)
+
+if(PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION)
+ set(PACKAGE_VERSION_EXACT TRUE)
+ set(PACKAGE_VERSION_COMPATIBLE TRUE)
+ set(PACKAGE_VERSION_UNSUITABLE FALSE)
+endif(PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION)
diff --git a/infra/cmake/packages/TensorFlowSource-2.12.1/TensorFlowSourceConfig.cmake b/infra/cmake/packages/TensorFlowSource-2.12.1/TensorFlowSourceConfig.cmake
new file mode 100644
index 000000000..81fc6aecb
--- /dev/null
+++ b/infra/cmake/packages/TensorFlowSource-2.12.1/TensorFlowSourceConfig.cmake
@@ -0,0 +1,19 @@
+function(_TensorFlowSource_import)
+ if(NOT DOWNLOAD_TENSORFLOW)
+ set(TensorFlowSource_FOUND FALSE PARENT_SCOPE)
+ return()
+ endif(NOT DOWNLOAD_TENSORFLOW)
+
+ nnas_include(ExternalSourceTools)
+ nnas_include(OptionTools)
+
+ envoption(EXTERNAL_DOWNLOAD_SERVER "https://github.com")
+ envoption(TENSORFLOW_2_12_1_URL ${EXTERNAL_DOWNLOAD_SERVER}/tensorflow/tensorflow/archive/v2.12.1.tar.gz)
+
+ ExternalSource_Download(TENSORFLOW DIRNAME TENSORFLOW-2.12.1 ${TENSORFLOW_2_12_1_URL})
+
+ set(TensorFlowSource_DIR ${TENSORFLOW_SOURCE_DIR} PARENT_SCOPE)
+ set(TensorFlowSource_FOUND TRUE PARENT_SCOPE)
+endfunction(_TensorFlowSource_import)
+
+_TensorFlowSource_import()
diff --git a/infra/cmake/packages/TensorFlowSource-2.12.1/TensorFlowSourceConfigVersion.cmake b/infra/cmake/packages/TensorFlowSource-2.12.1/TensorFlowSourceConfigVersion.cmake
new file mode 100644
index 000000000..8566d0816
--- /dev/null
+++ b/infra/cmake/packages/TensorFlowSource-2.12.1/TensorFlowSourceConfigVersion.cmake
@@ -0,0 +1,10 @@
+set(PACKAGE_VERSION "2.12.1")
+set(PACKAGE_VERSION_EXACT FALSE)
+set(PACKAGE_VERSION_COMPATIBLE FALSE)
+set(PACKAGE_VERSION_UNSUITABLE TRUE)
+
+if(PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION)
+ set(PACKAGE_VERSION_EXACT TRUE)
+ set(PACKAGE_VERSION_COMPATIBLE TRUE)
+ set(PACKAGE_VERSION_UNSUITABLE FALSE)
+endif(PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION)
diff --git a/infra/command/build-docker-image b/infra/command/build-docker-image
index 9a044385c..f4e2069c0 100644
--- a/infra/command/build-docker-image
+++ b/infra/command/build-docker-image
@@ -45,6 +45,12 @@ done
DOCKER_IMAGE_NAME=${DOCKER_IMAGE_NAME:-nnfw/one-devtools:$DOCKER_TAG}
DOCKER_FILE_RPATH=$DOCKER_FILE_RPATH_BASE/$UBUNTU_CODENAME/Dockerfile
+
+HOST_ARCH=$(uname -m)
+if [[ -n $HOST_ARCH && $HOST_ARCH != "x86_64" ]]; then
+ DOCKER_FILE_RPATH=$DOCKER_FILE_RPATH.$HOST_ARCH
+fi
+
DOCKER_BUILD_ARGS+=("-t ${DOCKER_IMAGE_NAME}")
docker build --build-arg http_proxy="${http_proxy}" \
diff --git a/infra/debian/compiler/changelog b/infra/debian/compiler/changelog
index ba5eea9a5..c4d358481 100644
--- a/infra/debian/compiler/changelog
+++ b/infra/debian/compiler/changelog
@@ -1,3 +1,22 @@
+one (1.24.0) bionic; urgency=medium
+
+ * Introduce _one-import-onnx_ extension interface
+ * _onecc_ supports profiling of multiple backends with a single cfg file
+ * Enable more Quantize operator: FloorMod, Squeeze
+ * _visq_ supports multi-out nodes
+ * _onecc_ introduces `dynamic_batch_to_single_batch option` option.
+
+ -- seongwoo <seongwoo@sw> Thu, 18 Jul 2023 14:10:22 +0900
+
+one (1.23.0) bionic; urgency=medium
+
+ * Support more Op(s): GeLU
+ * Support more option(s): `--fuse-gelu`
+ * Support multiple backends compilation with a single configuration file
+ * Upgrade Circle schema to 0.5
+
+ -- seongwoo <seongwoo@sw> Thu, 18 May 2023 19:10:21 +0900
+
one (1.22.0) bionic; urgency=medium
* Introduce new optimization options: `unroll_unidirseqlstm`, `forward_transpose_op`, `fold_fully_connected`, `fuse_prelu`
diff --git a/infra/debian/compiler/one-compiler.install b/infra/debian/compiler/one-compiler.install
index 641bbe6ae..700cc2d0a 100644
--- a/infra/debian/compiler/one-compiler.install
+++ b/infra/debian/compiler/one-compiler.install
@@ -3,6 +3,7 @@
usr/bin/circle2circle usr/share/one/bin/
usr/bin/circle-eval-diff usr/share/one/bin/
usr/bin/circle-interpreter usr/share/one/bin/
+usr/bin/circle-mpqsolver usr/share/one/bin/
usr/bin/circle-operator usr/share/one/bin/
usr/bin/circle-partitioner usr/share/one/bin/
usr/bin/circle-quantizer usr/share/one/bin/
@@ -28,6 +29,7 @@ usr/bin/one-prepare-venv usr/share/one/bin/
usr/bin/one-profile usr/share/one/bin/
usr/bin/one-quantize usr/share/one/bin/
usr/bin/one-version usr/share/one/bin/
+usr/bin/onelib/backends.py usr/share/one/bin/onelib/
usr/bin/onelib/constant.py usr/share/one/bin/onelib/
usr/bin/onelib/make_cmd.py usr/share/one/bin/onelib/
usr/bin/onelib/CfgRunner.py usr/share/one/bin/onelib/
@@ -49,6 +51,8 @@ usr/bin/visqlib/DumpFP32FM.py usr/share/one/bin/visqlib/
usr/bin/visqlib/Palette.py usr/share/one/bin/visqlib/
usr/bin/visqlib/QErrorComputer.py usr/share/one/bin/visqlib/
usr/bin/visqlib/Util.py usr/share/one/bin/visqlib/
+usr/bin/visqlib/DotBuilder.py usr/share/one/bin/visqlib/
+usr/bin/circle/*.py usr/share/one/bin/circle/
# lib
usr/lib/* usr/share/one/lib/
# doc
diff --git a/infra/debian/compiler/rules b/infra/debian/compiler/rules
index 447fb2192..e83680da8 100755
--- a/infra/debian/compiler/rules
+++ b/infra/debian/compiler/rules
@@ -1,7 +1,7 @@
#!/usr/bin/make -f
export DH_VERBOSE = 1
export NNAS_BUILD_PREFIX = build
-export PRESET = 20221125
+export PRESET = 20230413
export _DESTDIR = debian/tmp/usr
%:
diff --git a/infra/docker/bionic/Dockerfile.aarch64 b/infra/docker/bionic/Dockerfile.aarch64
new file mode 100644
index 000000000..08d712c96
--- /dev/null
+++ b/infra/docker/bionic/Dockerfile.aarch64
@@ -0,0 +1,92 @@
+# Copyright 2016-2020 Jing Li
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+FROM ubuntu:18.04
+
+ARG UBUNTU_MIRROR
+
+# Install 'add-apt-repository'
+RUN apt-get update && apt-get -qqy install software-properties-common
+
+# Git repo for latest version (github checkout@v2 action requires v2.18)
+RUN add-apt-repository ppa:git-core/ppa -y
+
+# Build tool
+RUN apt-get update && apt-get -qqy install build-essential cmake scons git g++-arm-linux-gnueabihf
+
+# ARM none eabi build tool
+RUN apt-get update && apt-get -qqy install gcc-arm-none-eabi
+
+# Debian build tool
+RUN apt-get update && apt-get -qqy install fakeroot devscripts debhelper python3-all
+
+# Install extra dependencies (Caffe, nnkit)
+RUN apt-get update && apt-get -qqy install libboost-all-dev libgflags-dev libgoogle-glog-dev libatlas-base-dev libhdf5-dev
+
+# Install protocol buffer
+RUN apt-get update && apt-get -qqy install libprotobuf-dev protobuf-compiler
+
+# Additonal tools
+RUN apt-get update && \
+ DEBIAN_FRONTEND=noninteractive \
+ apt-get -qqy install doxygen graphviz wget zip unzip clang-format-8 python3 python3-pip python3-venv python3-dev hdf5-tools pylint curl
+RUN apt-get update && apt-get -qqy install python3.8 python3.8-venv python3.8-dev
+RUN python3 -m pip install --upgrade pip
+RUN python3 -m pip install yapf==0.22.0 numpy flatbuffers
+RUN python3.8 -m pip install --upgrade pip
+RUN python3.8 -m pip install numpy flatbuffers
+
+# Install google test (source)
+RUN apt-get update && apt-get -qqy install libgtest-dev
+
+# Install build tool gcc version 8.x and set alternative link (c++17 support)
+RUN apt-get update && apt-get -qqy install g++-8 g++-8-arm-linux-gnueabihf
+RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 80 \
+ --slave /usr/bin/g++ g++ /usr/bin/g++-8 \
+ --slave /usr/bin/gcov gcov /usr/bin/gcov-8
+RUN update-alternatives --install /usr/bin/arm-linux-gnueabihf-gcc arm-linux-gnueabihf-gcc /usr/bin/arm-linux-gnueabihf-gcc-8 80 \
+ --slave /usr/bin/arm-linux-gnueabihf-g++ arm-linux-gnueabihf-g++ /usr/bin/arm-linux-gnueabihf-g++-8 \
+ --slave /usr/bin/arm-linux-gnueabihf-gcov arm-linux-gnueabihf-gcov /usr/bin/arm-linux-gnueabihf-gcov-8
+
+# Install lcov 1.14-2 for gcc-8 support
+# Default version lcov 1.13-3 can't support gcc-8
+# lcov 1.13-4 with gcc-8 have bug: reports no coverage for class declaration
+WORKDIR /root/lcov
+RUN wget http://archive.ubuntu.com/ubuntu/pool/universe/l/lcov/lcov_1.14-2_all.deb
+RUN apt-get update && apt-get -qqy install libperlio-gzip-perl libjson-perl
+RUN dpkg -i lcov_1.14-2_all.deb
+WORKDIR /root
+RUN rm -rf /root/lcov
+
+# Build and install google test static libraries
+WORKDIR /root/gtest
+RUN cmake /usr/src/gtest
+RUN make
+RUN mv *.a /usr/lib
+WORKDIR /root
+RUN rm -rf gtest
+
+# Setup user to match host user, and give superuser permissions
+ARG USER_ID=1000
+ARG GROUP_ID=${USER_ID}
+RUN addgroup --gid ${GROUP_ID} ubuntu && adduser --disabled-password --gecos '' --uid ${USER_ID} --gid ${GROUP_ID} ubuntu && usermod -aG sudo ubuntu
+RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
+RUN echo 'ubuntu ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
+
+# Clean archives (to reduce image size)
+RUN apt-get clean -y
+
+# Set user to the one we just created
+USER ${USER_ID}
diff --git a/infra/docker/focal/Dockerfile b/infra/docker/focal/Dockerfile
index 284857964..0c6c582e9 100644
--- a/infra/docker/focal/Dockerfile
+++ b/infra/docker/focal/Dockerfile
@@ -48,6 +48,52 @@ RUN wget http://download.tizen.org/sdk/tizenstudio/official/binary/sdb_4.2.19_ub
RUN unzip -d tmp sdb.zip && rm sdb.zip
RUN cp tmp/data/tools/sdb /usr/bin/. && rm -rf tmp/*
+# ARM none eabi build tool
+RUN apt-get update && apt-get -qqy install gcc-arm-none-eabi
+
+# Install java
+RUN apt-get install -y --no-install-recommends openjdk-8-jdk
+
+# download and install Gradle
+# https://services.gradle.org/distributions/
+ARG GRADLE_VERSION=6.4.1
+ARG GRADLE_DIST=bin
+RUN cd /opt && \
+ wget -q https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-${GRADLE_DIST}.zip && \
+ unzip gradle*.zip && \
+ ls -d */ | sed 's/\/*$//g' | xargs -I{} mv {} gradle && \
+ rm gradle*.zip
+
+# download and install Android SDK
+# https://developer.android.com/studio#command-tools
+ARG ANDROID_SDK_VERSION=6514223
+ENV ANDROID_SDK_ROOT /opt/android-sdk
+RUN mkdir -p ${ANDROID_SDK_ROOT}/cmdline-tools && \
+ wget -q https://dl.google.com/android/repository/commandlinetools-linux-${ANDROID_SDK_VERSION}_latest.zip && \
+ unzip *tools*linux*.zip -d ${ANDROID_SDK_ROOT}/cmdline-tools && \
+ rm *tools*linux*.zip
+
+# accept the license agreements of the SDK components
+RUN mkdir -p ${ANDROID_SDK_ROOT}/licenses
+RUN echo 24333f8a63b6825ea9c5514f83c2829b004d1fee > ${ANDROID_SDK_ROOT}/licenses/android-sdk-license
+RUN echo d56f5187479451eabf01fb78af6dfcb131a6481e >> ${ANDROID_SDK_ROOT}/licenses/android-sdk-license
+
+# Env variable for gradle build
+ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64
+ENV GRADLE_HOME /opt/gradle
+ENV PATH ${PATH}:${GRADLE_HOME}/bin:${ANDROID_SDK_ROOT}/cmdline-tools/tools/bin:${ANDROID_SDK_ROOT}/platform-tools
+ENV ANDROID_HOME ${ANDROID_SDK_ROOT}
+
+# Install NDK
+RUN sdkmanager --install "ndk;20.0.5594570"
+RUN sdkmanager "platform-tools"
+
+# Env for ko encoding build
+ENV LC_ALL "C.UTF-8"
+
+# setup adb server
+EXPOSE 5037
+
# Setup user to match host user, and give superuser permissions
ARG USER_ID=1000
ARG GROUP_ID=${USER_ID}
diff --git a/infra/docker/focal/Dockerfile.aarch64 b/infra/docker/focal/Dockerfile.aarch64
new file mode 100644
index 000000000..b63bbb10f
--- /dev/null
+++ b/infra/docker/focal/Dockerfile.aarch64
@@ -0,0 +1,62 @@
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+FROM ubuntu:20.04
+
+ARG UBUNTU_MIRROR
+
+# Install 'add-apt-repository'
+RUN apt-get update && apt-get -qqy install software-properties-common
+
+# Build tool
+RUN apt-get update && apt-get -qqy install build-essential cmake scons git lcov g++-arm-linux-gnueabihf
+
+# Debian build tool
+RUN apt-get update && apt-get -qqy install fakeroot devscripts debhelper python3-all dh-python
+
+# Install extra dependencies (Caffe, nnkit)
+RUN apt-get update && apt-get -qqy install libboost-all-dev libgflags-dev libgoogle-glog-dev libatlas-base-dev libhdf5-dev
+
+# Install protocol buffer
+RUN apt-get update && apt-get -qqy install libprotobuf-dev protobuf-compiler
+
+# Additonal tools
+RUN apt-get update && \
+ DEBIAN_FRONTEND=noninteractive \
+ apt-get -qqy install doxygen graphviz wget zip unzip clang-format-8 python3 python3-pip python3-venv python3-dev hdf5-tools pylint curl
+RUN python3 -m pip install --upgrade pip
+RUN python3 -m pip install yapf==0.22.0 numpy flatbuffers
+
+# Install google test (source)
+RUN apt-get update && apt-get -qqy install libgtest-dev
+
+# Install gbs & sdb
+RUN echo 'deb [trusted=yes] http://download.tizen.org/tools/latest-release/Ubuntu_20.04/ /' | cat >> /etc/apt/sources.list
+RUN apt-get update && apt-get -qqy install gbs
+RUN wget http://download.tizen.org/sdk/tizenstudio/official/binary/sdb_4.2.19_ubuntu-64.zip -O sdb.zip
+RUN unzip -d tmp sdb.zip && rm sdb.zip
+RUN cp tmp/data/tools/sdb /usr/bin/. && rm -rf tmp/*
+
+# Setup user to match host user, and give superuser permissions
+ARG USER_ID=1000
+ARG GROUP_ID=${USER_ID}
+RUN addgroup --gid ${GROUP_ID} ubuntu && adduser --disabled-password --gecos '' --uid ${USER_ID} --gid ${GROUP_ID} ubuntu && usermod -aG sudo ubuntu
+RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
+RUN echo 'ubuntu ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
+
+# Clean archives (to reduce image size)
+RUN apt-get clean -y
+
+# Set user to the one we just created
+USER ${USER_ID}
diff --git a/infra/docker/jammy/Dockerfile.aarch64 b/infra/docker/jammy/Dockerfile.aarch64
new file mode 100644
index 000000000..a6a449dd6
--- /dev/null
+++ b/infra/docker/jammy/Dockerfile.aarch64
@@ -0,0 +1,60 @@
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+FROM ubuntu:jammy
+
+ARG UBUNTU_MIRROR
+
+# Install 'add-apt-repository'
+RUN apt-get update && apt-get -qqy install software-properties-common
+
+# Build tool
+RUN apt-get update && apt-get -qqy install build-essential cmake scons git lcov g++-arm-linux-gnueabihf
+
+# Debian build tool
+RUN apt-get update && apt-get -qqy install fakeroot devscripts debhelper python3-all dh-python
+
+# Install extra dependencies (Caffe, nnkit)
+RUN apt-get update && apt-get -qqy install libboost-all-dev libgflags-dev libgoogle-glog-dev libatlas-base-dev libhdf5-dev
+
+# Install protocol buffer
+RUN apt-get update && apt-get -qqy install libprotobuf-dev protobuf-compiler
+
+# Additonal tools
+# TODO install clang-format (No official clang-format-8 package for ubuntu jammy)
+RUN apt-get update && \
+ DEBIAN_FRONTEND=noninteractive \
+ apt-get -qqy install doxygen graphviz wget zip unzip python3 python3-pip python3-venv python3-dev hdf5-tools pylint curl
+RUN python3 -m pip install --upgrade pip
+RUN python3 -m pip install yapf==0.22.0 numpy flatbuffers
+
+# Install google test (source)
+RUN apt-get update && apt-get -qqy install libgtest-dev
+
+# TODO: Install gbs & sdb
+# gbs & sdb are not support ubuntu jammy yet
+
+# Setup user to match host user, and give superuser permissions
+ARG USER_ID=1000
+ARG GROUP_ID=${USER_ID}
+RUN apt-get update && apt-get -qqy install sudo
+RUN addgroup --gid ${GROUP_ID} ubuntu && adduser --disabled-password --gecos '' --uid ${USER_ID} --gid ${GROUP_ID} ubuntu && usermod -aG sudo ubuntu
+RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
+RUN echo 'ubuntu ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
+
+# Clean archives (to reduce image size)
+RUN apt-get clean -y
+
+# Set user to the one we just created
+USER ${USER_ID}
diff --git a/infra/nncc/Makefile.arm32 b/infra/nncc/Makefile.arm32
index 97631fc9d..9ba57ddb2 100644
--- a/infra/nncc/Makefile.arm32
+++ b/infra/nncc/Makefile.arm32
@@ -26,7 +26,7 @@ ARM32_BUILD_ITEMS+=;pepper-csv2vec;crew
ARM32_BUILD_ITEMS+=;oops;pepper-assert
ARM32_BUILD_ITEMS+=;hermes;hermes-std
ARM32_BUILD_ITEMS+=;loco;locop;logo-core;logo
-ARM32_BUILD_ITEMS+=;safemain;mio-circle04;mio-tflite280
+ARM32_BUILD_ITEMS+=;safemain;mio-circle05;mio-tflite280;mio-circle06;mio-tflite2121
ARM32_BUILD_ITEMS+=;dio-hdf5
ARM32_BUILD_ITEMS+=;luci-compute
ARM32_BUILD_ITEMS+=;foder;circle-verify;souschef;arser;vconone
@@ -44,7 +44,7 @@ ARM32_HOST_ITEMS+=;pepper-csv2vec
ARM32_HOST_ITEMS+=;oops
ARM32_HOST_ITEMS+=;hermes;hermes-std
ARM32_HOST_ITEMS+=;loco;locop;logo-core;logo
-ARM32_HOST_ITEMS+=;safemain;mio-circle04;mio-tflite280
+ARM32_HOST_ITEMS+=;safemain;mio-circle05;mio-tflite280;mio-circle06;mio-tflite2121
ARM32_HOST_ITEMS+=;luci-compute
ARM32_HOST_ITEMS+=;foder;circle-verify;souschef;arser;vconone
ARM32_HOST_ITEMS+=;luci
diff --git a/infra/nncc/cmake/buildtool/config/config_aarch64-linux.cmake b/infra/nncc/cmake/buildtool/config/config_aarch64-linux.cmake
new file mode 100644
index 000000000..fcae94f28
--- /dev/null
+++ b/infra/nncc/cmake/buildtool/config/config_aarch64-linux.cmake
@@ -0,0 +1,13 @@
+#
+# aarch64 linux compile options
+#
+
+message(STATUS "Building for aarch64 Linux")
+
+# include linux common
+include("${CMAKE_CURRENT_LIST_DIR}/config_linux.cmake")
+
+# addition for arm-linux
+set(FLAGS_COMMON ${FLAGS_COMMON}
+ "-march=armv8-a"
+ )
diff --git a/infra/nncc/cmake/buildtool/config/config_aarch64-tizen.cmake b/infra/nncc/cmake/buildtool/config/config_aarch64-tizen.cmake
new file mode 100644
index 000000000..0f304ecf3
--- /dev/null
+++ b/infra/nncc/cmake/buildtool/config/config_aarch64-tizen.cmake
@@ -0,0 +1,17 @@
+#
+# aarch64 tizen compile options
+#
+
+message(STATUS "Building for AARCH64 Tizen")
+
+# Build flag for tizen
+set(CMAKE_C_FLAGS_DEBUG "-O -g -DDEBUG")
+set(CMAKE_CXX_FLAGS_DEBUG "-O -g -DDEBUG")
+
+# TODO : add and use option_tizen if something uncommon comes up
+# include linux common
+include("cmake/buildtool/config/config_linux.cmake")
+
+# addition for aarch64-tizen
+set(FLAGS_COMMON ${FLAGS_COMMON}
+ )
diff --git a/infra/nncc/cmake/buildtool/config/config_armv7hl-tizen.cmake b/infra/nncc/cmake/buildtool/config/config_armv7hl-tizen.cmake
new file mode 100644
index 000000000..fc6876a23
--- /dev/null
+++ b/infra/nncc/cmake/buildtool/config/config_armv7hl-tizen.cmake
@@ -0,0 +1,29 @@
+#
+# armv7l tizen compile options
+#
+
+message(STATUS "Building for ARMv7hl(hardfp) Tizen")
+
+# Build flag for tizen
+set(CMAKE_C_FLAGS_DEBUG "-O -g -DDEBUG")
+set(CMAKE_CXX_FLAGS_DEBUG "-O -g -DDEBUG")
+
+# TODO : add and use option_tizen if something uncommon comes up
+# include linux common
+include("cmake/buildtool/config/config_linux.cmake")
+
+# addition for arm-linux
+set(FLAGS_COMMON ${FLAGS_COMMON}
+ "-mtune=cortex-a8"
+ "-mfloat-abi=hard"
+ "-funsafe-math-optimizations"
+ )
+
+if(BUILD_ARM32_NEON)
+ set(FLAGS_COMMON ${FLAGS_COMMON}
+ "-mfpu=neon-vfpv4"
+ "-ftree-vectorize"
+ )
+else(BUILD_ARM32_NEON)
+ message(STATUS "ARMv7l: NEON is disabled")
+endif(BUILD_ARM32_NEON)
diff --git a/infra/nncc/cmake/buildtool/config/config_armv7l-tizen.cmake b/infra/nncc/cmake/buildtool/config/config_armv7l-tizen.cmake
new file mode 100644
index 000000000..b1ffe65c1
--- /dev/null
+++ b/infra/nncc/cmake/buildtool/config/config_armv7l-tizen.cmake
@@ -0,0 +1,29 @@
+#
+# armv7l tizen compile options
+#
+
+message(STATUS "Building for ARMv7l(softfp) Tizen")
+
+# Build flag for tizen
+set(CMAKE_C_FLAGS_DEBUG "-O -g -DDEBUG")
+set(CMAKE_CXX_FLAGS_DEBUG "-O -g -DDEBUG")
+
+# TODO : add and use option_tizen if something uncommon comes up
+# include linux common
+include("cmake/buildtool/config/config_linux.cmake")
+
+# addition for arm-linux
+set(FLAGS_COMMON ${FLAGS_COMMON}
+ "-mtune=cortex-a8"
+ "-mfloat-abi=softfp"
+ "-funsafe-math-optimizations"
+ )
+
+if(BUILD_ARM32_NEON)
+ set(FLAGS_COMMON ${FLAGS_COMMON}
+ "-mfpu=neon-vfpv4"
+ "-ftree-vectorize"
+ )
+else(BUILD_ARM32_NEON)
+ message(STATUS "ARMv7l: NEON is disabled")
+endif(BUILD_ARM32_NEON)
diff --git a/infra/nncc/cmake/buildtool/config/config_i686-tizen.cmake b/infra/nncc/cmake/buildtool/config/config_i686-tizen.cmake
new file mode 100644
index 000000000..3929e07fd
--- /dev/null
+++ b/infra/nncc/cmake/buildtool/config/config_i686-tizen.cmake
@@ -0,0 +1,17 @@
+#
+# i686 tizen compile options
+#
+
+message(STATUS "Building for i686 Tizen")
+
+# Build flag for tizen
+set(CMAKE_C_FLAGS_DEBUG "-O -g -DDEBUG")
+set(CMAKE_CXX_FLAGS_DEBUG "-O -g -DDEBUG")
+
+# TODO : add and use option_tizen if something uncommon comes up
+# include linux common
+include("cmake/buildtool/config/config_linux.cmake")
+
+# addition for i686-tizen
+set(FLAGS_COMMON ${FLAGS_COMMON}
+ )
diff --git a/infra/nncc/cmake/buildtool/config/config_x86_64-tizen.cmake b/infra/nncc/cmake/buildtool/config/config_x86_64-tizen.cmake
new file mode 100644
index 000000000..0f304ecf3
--- /dev/null
+++ b/infra/nncc/cmake/buildtool/config/config_x86_64-tizen.cmake
@@ -0,0 +1,17 @@
+#
+# aarch64 tizen compile options
+#
+
+message(STATUS "Building for AARCH64 Tizen")
+
+# Build flag for tizen
+set(CMAKE_C_FLAGS_DEBUG "-O -g -DDEBUG")
+set(CMAKE_CXX_FLAGS_DEBUG "-O -g -DDEBUG")
+
+# TODO : add and use option_tizen if something uncommon comes up
+# include linux common
+include("cmake/buildtool/config/config_linux.cmake")
+
+# addition for aarch64-tizen
+set(FLAGS_COMMON ${FLAGS_COMMON}
+ )
diff --git a/infra/nncc/cmake/options/options_aarch64-darwin.cmake b/infra/nncc/cmake/options/options_aarch64-darwin.cmake
new file mode 100644
index 000000000..89398bdf4
--- /dev/null
+++ b/infra/nncc/cmake/options/options_aarch64-darwin.cmake
@@ -0,0 +1,4 @@
+#
+# aarch64 darwin cmake options
+#
+
diff --git a/infra/nncc/cmake/options/options_aarch64-linux.cmake b/infra/nncc/cmake/options/options_aarch64-linux.cmake
new file mode 100644
index 000000000..becd574b1
--- /dev/null
+++ b/infra/nncc/cmake/options/options_aarch64-linux.cmake
@@ -0,0 +1,4 @@
+#
+# aarch64 linux cmake options
+#
+
diff --git a/infra/nncc/cmake/options/options_aarch64-tizen.cmake b/infra/nncc/cmake/options/options_aarch64-tizen.cmake
new file mode 100644
index 000000000..be97cb314
--- /dev/null
+++ b/infra/nncc/cmake/options/options_aarch64-tizen.cmake
@@ -0,0 +1,4 @@
+#
+# aarch64 tizen cmake options
+#
+
diff --git a/infra/nncc/cmake/options/options_armv7hl-tizen.cmake b/infra/nncc/cmake/options/options_armv7hl-tizen.cmake
new file mode 100644
index 000000000..e787ecef8
--- /dev/null
+++ b/infra/nncc/cmake/options/options_armv7hl-tizen.cmake
@@ -0,0 +1,5 @@
+#
+# armv7hl tizen cmake options
+#
+
+option(BUILD_ARM32_NEON "Use NEON for ARM32 build" ON)
diff --git a/infra/nncc/cmake/options/options_armv7l-tizen.cmake b/infra/nncc/cmake/options/options_armv7l-tizen.cmake
new file mode 100644
index 000000000..9a96f403a
--- /dev/null
+++ b/infra/nncc/cmake/options/options_armv7l-tizen.cmake
@@ -0,0 +1,5 @@
+#
+# armv7l tizen cmake options
+#
+
+option(BUILD_ARM32_NEON "Use NEON for ARM32 build" ON)
diff --git a/infra/nncc/cmake/options/options_i686-tizen.cmake b/infra/nncc/cmake/options/options_i686-tizen.cmake
new file mode 100644
index 000000000..028efca97
--- /dev/null
+++ b/infra/nncc/cmake/options/options_i686-tizen.cmake
@@ -0,0 +1,3 @@
+#
+# i686 tizen cmake options
+#
diff --git a/infra/nncc/cmake/options/options_x86_64-darwin.cmake b/infra/nncc/cmake/options/options_x86_64-darwin.cmake
new file mode 100644
index 000000000..1a29135b4
--- /dev/null
+++ b/infra/nncc/cmake/options/options_x86_64-darwin.cmake
@@ -0,0 +1,4 @@
+#
+# x86_64 darwin cmake options
+#
+
diff --git a/infra/nncc/cmake/options/options_x86_64-tizen.cmake b/infra/nncc/cmake/options/options_x86_64-tizen.cmake
new file mode 100644
index 000000000..a29a0afc2
--- /dev/null
+++ b/infra/nncc/cmake/options/options_x86_64-tizen.cmake
@@ -0,0 +1,3 @@
+#
+# x86_64 tizen cmake options
+#
diff --git a/infra/nnfw/CMakeLists.txt b/infra/nnfw/CMakeLists.txt
index bb55a8f1c..857c15bf5 100644
--- a/infra/nnfw/CMakeLists.txt
+++ b/infra/nnfw/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16.3)
project(nnfw)
@@ -6,7 +6,7 @@ enable_testing()
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
-set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib:$ORIGIN/")
+set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib:$ORIGIN/../lib/nnfw/odc:$ORIGIN/")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
### CMAKE_BUILD_TYPE_LC: Build type lower case
diff --git a/infra/nnfw/cmake/CfgOptionFlags.cmake b/infra/nnfw/cmake/CfgOptionFlags.cmake
index b2f4da58c..8d37cf27c 100644
--- a/infra/nnfw/cmake/CfgOptionFlags.cmake
+++ b/infra/nnfw/cmake/CfgOptionFlags.cmake
@@ -20,6 +20,7 @@ option(BUILD_RUNTIME_NNFW_API_TEST "Build Runtime NNFW API Tests" ON)
option(BUILD_TFLITE_RUN "Build tflite-run" ON)
option(BUILD_TFLITE_VANILLA_RUN "Build tflite-vanilla-run" OFF)
option(BUILD_ONERT_RUN "Build onert_run" ON)
+option(BUILD_ONERT_TRAIN "Build onert_train" ON)
option(BUILD_TFLITE_LOADER "Build TensorFlow Lite loader" ON)
option(BUILD_CIRCLE_LOADER "Build circle loader" ON)
option(BUILD_TRIX_LOADER "Build trix loader" ON)
@@ -31,6 +32,8 @@ option(INSTALL_TEST_SCRIPTS "Install test scripts" ON)
option(BUILD_GPU_CL "Build gpu_cl backend" OFF)
option(BUILD_NPUD "Build NPU daemon" OFF)
option(ENVVAR_NPUD_CONFIG "Use environment variable for npud configuration" OFF)
+option(BUILD_MINMAX_H5DUMPER "Build minmax h5dumper" ON)
+option(ENABLE_ONERT_TRAIN "Enable onert training feature" ON)
#
# Default build configuration for contrib
#
diff --git a/infra/nnfw/cmake/buildtool/config/config_linux.cmake b/infra/nnfw/cmake/buildtool/config/config_linux.cmake
index 01b47ef4a..681d165d2 100644
--- a/infra/nnfw/cmake/buildtool/config/config_linux.cmake
+++ b/infra/nnfw/cmake/buildtool/config/config_linux.cmake
@@ -10,3 +10,8 @@ set(FLAGS_CXXONLY ${FLAGS_CXXONLY} "-Wno-ignored-attributes")
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0)
list(APPEND FLAGS_CXXONLY "-Wno-psabi")
endif()
+
+# Build fail on memcpy (ex. compute/cker/include/cker/Shape.h:211:16)
+if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 12.0)
+ list(APPEND FLAGS_CXXONLY "-Wno-error=stringop-overflow -Wno-error=array-bounds")
+endif()
diff --git a/infra/nnfw/cmake/buildtool/cross/toolchain_armv7l-tizen.cmake b/infra/nnfw/cmake/buildtool/cross/toolchain_armv7l-tizen.cmake
deleted file mode 100644
index 181415df2..000000000
--- a/infra/nnfw/cmake/buildtool/cross/toolchain_armv7l-tizen.cmake
+++ /dev/null
@@ -1,56 +0,0 @@
-#
-# config for arm-linux
-#
-include(CMakeForceCompiler)
-
-set(CMAKE_SYSTEM_NAME Linux)
-set(CMAKE_SYSTEM_PROCESSOR armv7l)
-
-set(CMAKE_C_COMPILER arm-linux-gnueabi-gcc)
-set(CMAKE_CXX_COMPILER arm-linux-gnueabi-g++)
-
-set(TIZEN_TOOLCHAIN "armv7l-tizen-linux-gnueabi/6.2.1")
-
-# where is the target environment
-set(NNAS_PROJECT_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../../..")
-set(ROOTFS_ARM "${NNAS_PROJECT_SOURCE_DIR}/tools/cross/rootfs/armel")
-include("${NNAS_PROJECT_SOURCE_DIR}/infra/cmake/modules/OptionTools.cmake")
-
-envoption(ROOTFS_DIR ${ROOTFS_ARM})
-if(NOT EXISTS "${ROOTFS_DIR}/usr/lib/gcc/${TIZEN_TOOLCHAIN}")
- message(FATAL_ERROR "Please prepare RootFS for tizen ARM softfp")
-endif()
-
-set(CMAKE_SYSROOT ${ROOTFS_DIR})
-set(CMAKE_FIND_ROOT_PATH ${ROOTFS_DIR})
-
-# search for programs in the build host directories
-set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
-
-# for libraries and headers in the target directories
-set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
-set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
-
-# Set cache variable to ignore try-run error by find_package(Threads REQUIRED) on cross build
-set(THREADS_PTHREAD_ARG "2" CACHE STRING "Result from TRY_RUN" FORCE)
-
-
-add_compile_options(-mthumb)
-add_compile_options(-mfpu=neon-vfpv4)
-add_compile_options(-mfloat-abi=softfp)
-add_compile_options(--sysroot=${ROOTFS_DIR})
-
-include_directories(SYSTEM ${ROOTFS_DIR}/usr/lib/gcc/${TIZEN_TOOLCHAIN}/include/c++/)
-include_directories(SYSTEM ${ROOTFS_DIR}/usr/lib/gcc/${TIZEN_TOOLCHAIN}/include/c++/armv7l-tizen-linux-gnueabi)
-add_compile_options(-Wno-deprecated-declarations) # compile-time option
-add_compile_options(-D__extern_always_inline=inline) # compile-time option
-
-set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -B${ROOTFS_DIR}/usr/lib/gcc/${TIZEN_TOOLCHAIN}")
-set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -L${ROOTFS_DIR}/lib")
-set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -L${ROOTFS_DIR}/usr/lib")
-set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -L${ROOTFS_DIR}/usr/lib/gcc/${TIZEN_TOOLCHAIN}")
-
-set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -B${ROOTFS_DIR}/usr/lib/gcc/${TIZEN_TOOLCHAIN}")
-set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${ROOTFS_DIR}/lib")
-set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${ROOTFS_DIR}/usr/lib")
-set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${ROOTFS_DIR}/usr/lib/gcc/${TIZEN_TOOLCHAIN}")
diff --git a/infra/nnfw/cmake/options/options_aarch64-android.cmake b/infra/nnfw/cmake/options/options_aarch64-android.cmake
index 242dcd3c6..5de2be333 100644
--- a/infra/nnfw/cmake/options/options_aarch64-android.cmake
+++ b/infra/nnfw/cmake/options/options_aarch64-android.cmake
@@ -14,3 +14,5 @@ option(DOWNLOAD_OPENCL_HEADERS "Download Opencl_headers source" ON)
option(DOWNLOAD_PYBIND11 "Download Pybind11 source" ON)
option(BUILD_GPU_CL "Build gpu_cl backend" ON)
option(BUILD_TENSORFLOW_LITE_GPU "Build TensorFlow Lite GPU delegate from the downloaded source" ON)
+
+option(BUILD_MINMAX_H5DUMPER "Build minmax h5dumper" OFF)
diff --git a/infra/nnfw/cmake/options/options_aarch64-tizen.cmake b/infra/nnfw/cmake/options/options_aarch64-tizen.cmake
index daaa4c449..cccd77f98 100644
--- a/infra/nnfw/cmake/options/options_aarch64-tizen.cmake
+++ b/infra/nnfw/cmake/options/options_aarch64-tizen.cmake
@@ -14,3 +14,6 @@ option(ENVVAR_ONERT_CONFIG "Use environment variable for onert configuration" OF
option(BUILD_NPUD "Build NPU daemon" ON)
# Do not allow to use CONFIG option on Tizen
option(ENVVAR_NPUD_CONFIG "Use environment variable for npud configuration" OFF)
+
+option(BUILD_MINMAX_H5DUMPER "Build minmax h5dumper" OFF)
+option(ENABLE_ONERT_TRAIN "Enable onert training feature" OFF)
diff --git a/infra/nnfw/cmake/options/options_armv7hl-tizen.cmake b/infra/nnfw/cmake/options/options_armv7hl-tizen.cmake
index e28801f87..07dc0404e 100644
--- a/infra/nnfw/cmake/options/options_armv7hl-tizen.cmake
+++ b/infra/nnfw/cmake/options/options_armv7hl-tizen.cmake
@@ -22,3 +22,6 @@ option(BUILD_TENSORFLOW_LITE_GPU "Build TensorFlow Lite GPU delegate from the do
option(BUILD_NPUD "Build NPU daemon" ON)
# Do not allow to use CONFIG option on Tizen
option(ENVVAR_NPUD_CONFIG "Use environment variable for npud configuration" OFF)
+
+option(BUILD_MINMAX_H5DUMPER "Build minmax h5dumper" OFF)
+option(ENABLE_ONERT_TRAIN "Enable onert training feature" OFF)
diff --git a/infra/nnfw/cmake/options/options_armv7l-tizen.cmake b/infra/nnfw/cmake/options/options_armv7l-tizen.cmake
index c5f4a2cc6..4fdcbc33f 100644
--- a/infra/nnfw/cmake/options/options_armv7l-tizen.cmake
+++ b/infra/nnfw/cmake/options/options_armv7l-tizen.cmake
@@ -22,3 +22,6 @@ option(BUILD_TENSORFLOW_LITE_GPU "Build TensorFlow Lite GPU delegate from the do
option(BUILD_NPUD "Build NPU daemon" ON)
# Do not allow to use CONFIG option on Tizen
option(ENVVAR_NPUD_CONFIG "Use environment variable for npud configuration" OFF)
+
+option(BUILD_MINMAX_H5DUMPER "Build minmax h5dumper" OFF)
+option(ENABLE_ONERT_TRAIN "Enable onert training feature" OFF)
diff --git a/infra/nnfw/cmake/options/options_i686-tizen.cmake b/infra/nnfw/cmake/options/options_i686-tizen.cmake
index 14a3d555b..e51f5ed7b 100644
--- a/infra/nnfw/cmake/options/options_i686-tizen.cmake
+++ b/infra/nnfw/cmake/options/options_i686-tizen.cmake
@@ -11,3 +11,6 @@ option(GENERATE_RUNTIME_NNAPI_TESTS "Generate NNAPI operation gtest" OFF)
option(ENVVAR_ONERT_CONFIG "Use environment variable for onert configuration" OFF)
option(BUILD_XNNPACK "Build XNNPACK" OFF)
+
+option(BUILD_MINMAX_H5DUMPER "Build minmax h5dumper" OFF)
+option(ENABLE_ONERT_TRAIN "Enable onert training feature" OFF)
diff --git a/infra/nnfw/cmake/options/options_x86_64-tizen.cmake b/infra/nnfw/cmake/options/options_x86_64-tizen.cmake
index 24b4d95f8..70da68c82 100644
--- a/infra/nnfw/cmake/options/options_x86_64-tizen.cmake
+++ b/infra/nnfw/cmake/options/options_x86_64-tizen.cmake
@@ -16,3 +16,6 @@ option(DOWNLOAD_OPENCL_HEADERS "Download opencl headers" OFF)
option(BUILD_NPUD "Build NPU daemon" ON)
# Do not allow to use CONFIG option on Tizen
option(ENVVAR_NPUD_CONFIG "Use environment variable for npud configuration" OFF)
+
+option(BUILD_MINMAX_H5DUMPER "Build minmax h5dumper" OFF)
+option(ENABLE_ONERT_TRAIN "Enable onert training feature" OFF)
diff --git a/infra/nnfw/cmake/packages/LuciConfig.cmake b/infra/nnfw/cmake/packages/LuciConfig.cmake
new file mode 100644
index 000000000..426556b3a
--- /dev/null
+++ b/infra/nnfw/cmake/packages/LuciConfig.cmake
@@ -0,0 +1,43 @@
+# Assume that luci and related libraries and headers are installed on overlay directory
+
+set(Luci_FOUND FALSE)
+
+find_path(LUCI_HEADERS
+ NAMES loco.h luci/IR/CircleNode.h
+ PATHS ${EXT_OVERLAY_DIR}/include)
+
+macro(_load_library LUCI_NAME)
+ add_library(luci::${LUCI_NAME} SHARED IMPORTED)
+ find_library(LUCI_LIB_PATH_${LUCI_NAME} NAMES luci_${LUCI_NAME} PATHS ${EXT_OVERLAY_DIR}/lib)
+ if (NOT LUCI_LIB_PATH_${LUCI_NAME})
+ return()
+ endif()
+ set_target_properties(luci::${LUCI_NAME} PROPERTIES
+ IMPORTED_LOCATION ${LUCI_LIB_PATH_${LUCI_NAME}}
+ INTERFACE_INCLUDE_DIRECTORIES ${LUCI_HEADERS})
+endmacro()
+
+_load_library(env)
+_load_library(export)
+_load_library(import)
+_load_library(lang)
+_load_library(logex)
+_load_library(log)
+_load_library(partition)
+_load_library(pass)
+_load_library(plan)
+_load_library(profile)
+_load_library(service)
+
+# Need luci::loco to avoid "DSO missing from command line" link error
+# TODO Find better way to do this
+add_library(luci::loco SHARED IMPORTED)
+find_library(LOCO_LIB_PATH NAMES loco PATHS ${EXT_OVERLAY_DIR}/lib)
+if (NOT LOCO_LIB_PATH)
+ return()
+endif()
+set_target_properties(luci::loco PROPERTIES
+ IMPORTED_LOCATION ${LOCO_LIB_PATH}
+ INTERFACE_INCLUDE_DIRECTORIES ${LUCI_HEADERS})
+
+set(Luci_FOUND TRUE)
diff --git a/infra/packaging/build b/infra/packaging/build
index 0c1370faa..16bce7e0e 100644
--- a/infra/packaging/build
+++ b/infra/packaging/build
@@ -8,7 +8,7 @@ if [[ -z "${NNAS_PROJECT_PATH}" ]]; then
fi
# The default preset
-PRESET="20221125"
+PRESET="20230413"
# Test is enabled by default
DISABLE_TEST=false
diff --git a/infra/packaging/preset/20230413 b/infra/packaging/preset/20230413
new file mode 100644
index 000000000..85ce6cbc6
--- /dev/null
+++ b/infra/packaging/preset/20230413
@@ -0,0 +1,66 @@
+#!/bin/bash
+
+# NOTE purpose of this file is static analysis only
+# new official preset will be added when new programs are ready
+
+PRESET="20230413"
+
+function preset_configure()
+{
+ REQUIRED_UNITS=()
+ # Common Libraries
+ REQUIRED_UNITS+=("angkor" "cwrap" "pepper-str" "pepper-strcast" "pp")
+ REQUIRED_UNITS+=("oops" "pepper-assert" "pepper-csv2vec" "foder" "crew")
+ REQUIRED_UNITS+=("souschef")
+ REQUIRED_UNITS+=("safemain")
+ REQUIRED_UNITS+=("arser")
+ REQUIRED_UNITS+=("vconone")
+ # Hermes Logging Framework
+ REQUIRED_UNITS+=("hermes" "hermes-std")
+ # loco IR and related utilities
+ REQUIRED_UNITS+=("loco" "locop" "locomotiv" "logo-core" "logo")
+ # Flatbuffer I/O
+ REQUIRED_UNITS+=("mio-tflite280" "mio-circle05" "mio-tflite2121" "mio-circle06")
+ # Data I/O
+ REQUIRED_UNITS+=("dio-hdf5")
+ # Compute
+ REQUIRED_UNITS+=("luci-compute")
+ # Circle compiler library (.circle -> .circle)
+ REQUIRED_UNITS+=("luci")
+ # Python interface for circle schema
+ REQUIRED_UNITS+=("pics")
+ # Tools
+ REQUIRED_UNITS+=("tflite2circle" "circle2circle" "tflchef")
+ REQUIRED_UNITS+=("circle-tensordump" "circledump")
+ REQUIRED_UNITS+=("tf2tfliteV2" "luci-interpreter")
+ REQUIRED_UNITS+=("luci-eval-driver")
+ REQUIRED_UNITS+=("record-minmax" "circle-quantizer" "rawdata2hdf5" "circle-mpqsolver")
+ REQUIRED_UNITS+=("circle-eval-diff" "circle-interpreter")
+ REQUIRED_UNITS+=("circle-partitioner" "circle-operator")
+ REQUIRED_UNITS+=("one-cmds")
+ REQUIRED_UNITS+=("bcq-tools")
+ REQUIRED_UNITS+=("dalgona")
+ REQUIRED_UNITS+=("visq")
+ REQUIRED_UNITS+=("circle-opselector")
+
+ # Dependent modules needed for build
+ REQUIRED_UNITS+=("circlechef")
+ REQUIRED_UNITS+=("circle-verify")
+
+ NPROC=${NPROC:-$(cat /proc/cpuinfo | grep -c processor)}
+
+ # TODO Use "nncc configure" and "nncc build"
+ cmake \
+ -DCMAKE_INSTALL_PREFIX="${NNCC_INSTALL_PREFIX}" \
+ -DCMAKE_BUILD_TYPE=release \
+ -DBUILD_WHITELIST=$(join_by ";" "${REQUIRED_UNITS[@]}") \
+ -DEXTERNALS_BUILD_THREADS=$((NPROC/2)) \
+ ${EXTRA_OPTIONS[@]} \
+ "${NNAS_PROJECT_PATH}/infra/nncc"
+}
+
+function preset_install()
+{
+ # Install tf2nnpkg
+ install -T -m 755 -D "${SCRIPT_PATH}/res/tf2nnpkg.${PRESET}" "${NNAS_INSTALL_PREFIX}/bin/tf2nnpkg"
+}
diff --git a/infra/packaging/preset/20230413_windows b/infra/packaging/preset/20230413_windows
new file mode 100644
index 000000000..8015de86d
--- /dev/null
+++ b/infra/packaging/preset/20230413_windows
@@ -0,0 +1,80 @@
+#!/bin/bash
+
+PRESET="20230413"
+
+function preset_configure()
+{
+ REQUIRED_UNITS=()
+ # Common Libraries
+ REQUIRED_UNITS+=("angkor" "cwrap" "pepper-str" "pepper-strcast" "pp")
+ REQUIRED_UNITS+=("oops" "pepper-assert" "pepper-csv2vec" "foder" "crew")
+ REQUIRED_UNITS+=("souschef")
+ REQUIRED_UNITS+=("safemain")
+ REQUIRED_UNITS+=("arser")
+ REQUIRED_UNITS+=("vconone")
+ # Hermes Logging Framework
+ REQUIRED_UNITS+=("hermes" "hermes-std")
+ # loco IR and related utilities
+ REQUIRED_UNITS+=("loco" "locop" "locomotiv" "logo-core" "logo")
+ # Flatbuffer I/O
+ REQUIRED_UNITS+=("mio-tflite280" "mio-circle05" "mio-tflite2121" "mio-circle06")
+ # Data I/O
+ REQUIRED_UNITS+=("dio-hdf5")
+ # Compute
+ REQUIRED_UNITS+=("luci-compute")
+ # Circle compiler library (.circle -> .circle)
+ REQUIRED_UNITS+=("luci")
+ # Python interface for circle schema
+ REQUIRED_UNITS+=("pics")
+ # Tools
+ REQUIRED_UNITS+=("tflite2circle" "circle2circle" "tflchef")
+ REQUIRED_UNITS+=("circle-tensordump" "circledump")
+ REQUIRED_UNITS+=("tf2tfliteV2" "luci-interpreter")
+ REQUIRED_UNITS+=("luci-eval-driver")
+ REQUIRED_UNITS+=("record-minmax" "circle-quantizer" "rawdata2hdf5" "circle-mpqsolver")
+ REQUIRED_UNITS+=("circle-eval-diff" "circle-interpreter")
+ REQUIRED_UNITS+=("circle-partitioner" "circle-operator")
+ REQUIRED_UNITS+=("one-cmds")
+ REQUIRED_UNITS+=("bcq-tools")
+ REQUIRED_UNITS+=("dalgona")
+ REQUIRED_UNITS+=("visq")
+
+ # Dependent modules needed for build
+ REQUIRED_UNITS+=("circlechef")
+ REQUIRED_UNITS+=("circle-verify")
+
+ NPROC=$(cat /proc/cpuinfo | grep -c processor)
+
+ # TODO Use "nncc configure" and "nncc build"
+ cmake \
+ -G "MSYS Makefiles" \
+ -DUSE_PROTOBUF_LEGACY_IMPORT=ON \
+ -DCMAKE_EXE_LINKER_FLAGS="-Wl,--allow-multiple-definition" \
+ -DCMAKE_SHARED_LINKER_FLAGS="-Wl,--allow-multiple-definition" \
+ -DENABLE_TEST=OFF \
+ -DDOWNLOAD_GTEST=OFF \
+ -DBUILD_GTEST=OFF \
+ -DCMAKE_C_COMPILER=gcc \
+ -DCMAKE_CXX_COMPILER=g++ \
+ -DCMAKE_INSTALL_PREFIX="${NNCC_INSTALL_PREFIX}" \
+ -DCMAKE_BUILD_TYPE=release \
+ -DBUILD_WHITELIST=$(join_by ";" "${REQUIRED_UNITS[@]}") \
+ -DEXTERNALS_BUILD_THREADS=$((NPROC/2)) \
+ ${EXTRA_OPTIONS[@]} \
+ "${NNAS_PROJECT_PATH}/infra/nncc"
+}
+
+function preset_install()
+{
+ # Install libraries to bin/ for Windows release
+ mv ${NNCC_INSTALL_PREFIX}/lib/*.dll ${NNCC_INSTALL_PREFIX}/bin
+ rm -rf ${NNCC_INSTALL_PREFIX}/lib
+
+ # Install tf2nnpkg
+ install -T -m 755 -D "${SCRIPT_PATH}/res/tf2nnpkg.${PRESET}" "${NNAS_INSTALL_PREFIX}/bin/tf2nnpkg"
+
+ # Though you have to install tensorflow to run 'tf2tfliteV2',
+ # tensorflow can't be installed in mingw. First, You can install tensorflow
+ # from Window native CMD(run as administrator) with python virtual environment.
+ # And, you must copy it to "${NNAS_INSTALL_PREFIX}/bin/venv"
+}
diff --git a/infra/packaging/preset/20230907 b/infra/packaging/preset/20230907
new file mode 100644
index 000000000..44bc4e00f
--- /dev/null
+++ b/infra/packaging/preset/20230907
@@ -0,0 +1,66 @@
+#!/bin/bash
+
+# NOTE purpose of this file is static analysis only
+# new official preset will be added when new programs are ready
+
+PRESET="20230907"
+
+function preset_configure()
+{
+ REQUIRED_UNITS=()
+ # Common Libraries
+ REQUIRED_UNITS+=("angkor" "cwrap" "pepper-str" "pepper-strcast" "pp")
+ REQUIRED_UNITS+=("oops" "pepper-assert" "pepper-csv2vec" "foder" "crew")
+ REQUIRED_UNITS+=("souschef")
+ REQUIRED_UNITS+=("safemain")
+ REQUIRED_UNITS+=("arser")
+ REQUIRED_UNITS+=("vconone")
+ # Hermes Logging Framework
+ REQUIRED_UNITS+=("hermes" "hermes-std")
+ # loco IR and related utilities
+ REQUIRED_UNITS+=("loco" "locop" "locomotiv" "logo-core" "logo")
+ # Flatbuffer I/O
+ REQUIRED_UNITS+=("mio-tflite2121" "mio-circle06")
+ # Data I/O
+ REQUIRED_UNITS+=("dio-hdf5")
+ # Compute
+ REQUIRED_UNITS+=("luci-compute")
+ # Circle compiler library (.circle -> .circle)
+ REQUIRED_UNITS+=("luci")
+ # Python interface for circle schema
+ REQUIRED_UNITS+=("pics")
+ # Tools
+ REQUIRED_UNITS+=("tflite2circle" "circle2circle" "tflchef")
+ REQUIRED_UNITS+=("circle-tensordump" "circledump")
+ REQUIRED_UNITS+=("tf2tfliteV2" "luci-interpreter")
+ REQUIRED_UNITS+=("luci-eval-driver")
+ REQUIRED_UNITS+=("record-minmax" "circle-quantizer" "rawdata2hdf5" "circle-mpqsolver")
+ REQUIRED_UNITS+=("circle-eval-diff" "circle-interpreter")
+ REQUIRED_UNITS+=("circle-partitioner" "circle-operator")
+ REQUIRED_UNITS+=("one-cmds")
+ REQUIRED_UNITS+=("bcq-tools")
+ REQUIRED_UNITS+=("dalgona")
+ REQUIRED_UNITS+=("visq")
+ REQUIRED_UNITS+=("circle-opselector")
+
+ # Dependent modules needed for build
+ REQUIRED_UNITS+=("circlechef")
+ REQUIRED_UNITS+=("circle-verify")
+
+ NPROC=${NPROC:-$(cat /proc/cpuinfo | grep -c processor)}
+
+ # TODO Use "nncc configure" and "nncc build"
+ cmake \
+ -DCMAKE_INSTALL_PREFIX="${NNCC_INSTALL_PREFIX}" \
+ -DCMAKE_BUILD_TYPE=release \
+ -DBUILD_WHITELIST=$(join_by ";" "${REQUIRED_UNITS[@]}") \
+ -DEXTERNALS_BUILD_THREADS=$((NPROC/2)) \
+ ${EXTRA_OPTIONS[@]} \
+ "${NNAS_PROJECT_PATH}/infra/nncc"
+}
+
+function preset_install()
+{
+ # Install tf2nnpkg
+ install -T -m 755 -D "${SCRIPT_PATH}/res/tf2nnpkg.${PRESET}" "${NNAS_INSTALL_PREFIX}/bin/tf2nnpkg"
+}
diff --git a/infra/packaging/preset/20230907_windows b/infra/packaging/preset/20230907_windows
new file mode 100644
index 000000000..5dcb36ab0
--- /dev/null
+++ b/infra/packaging/preset/20230907_windows
@@ -0,0 +1,80 @@
+#!/bin/bash
+
+PRESET="20230907"
+
+function preset_configure()
+{
+ REQUIRED_UNITS=()
+ # Common Libraries
+ REQUIRED_UNITS+=("angkor" "cwrap" "pepper-str" "pepper-strcast" "pp")
+ REQUIRED_UNITS+=("oops" "pepper-assert" "pepper-csv2vec" "foder" "crew")
+ REQUIRED_UNITS+=("souschef")
+ REQUIRED_UNITS+=("safemain")
+ REQUIRED_UNITS+=("arser")
+ REQUIRED_UNITS+=("vconone")
+ # Hermes Logging Framework
+ REQUIRED_UNITS+=("hermes" "hermes-std")
+ # loco IR and related utilities
+ REQUIRED_UNITS+=("loco" "locop" "locomotiv" "logo-core" "logo")
+ # Flatbuffer I/O
+ REQUIRED_UNITS+=("mio-tflite2121" "mio-circle06")
+ # Data I/O
+ REQUIRED_UNITS+=("dio-hdf5")
+ # Compute
+ REQUIRED_UNITS+=("luci-compute")
+ # Circle compiler library (.circle -> .circle)
+ REQUIRED_UNITS+=("luci")
+ # Python interface for circle schema
+ REQUIRED_UNITS+=("pics")
+ # Tools
+ REQUIRED_UNITS+=("tflite2circle" "circle2circle" "tflchef")
+ REQUIRED_UNITS+=("circle-tensordump" "circledump")
+ REQUIRED_UNITS+=("tf2tfliteV2" "luci-interpreter")
+ REQUIRED_UNITS+=("luci-eval-driver")
+ REQUIRED_UNITS+=("record-minmax" "circle-quantizer" "rawdata2hdf5" "circle-mpqsolver")
+ REQUIRED_UNITS+=("circle-eval-diff" "circle-interpreter")
+ REQUIRED_UNITS+=("circle-partitioner" "circle-operator")
+ REQUIRED_UNITS+=("one-cmds")
+ REQUIRED_UNITS+=("bcq-tools")
+ REQUIRED_UNITS+=("dalgona")
+ REQUIRED_UNITS+=("visq")
+
+ # Dependent modules needed for build
+ REQUIRED_UNITS+=("circlechef")
+ REQUIRED_UNITS+=("circle-verify")
+
+ NPROC=$(cat /proc/cpuinfo | grep -c processor)
+
+ # TODO Use "nncc configure" and "nncc build"
+ cmake \
+ -G "MSYS Makefiles" \
+ -DUSE_PROTOBUF_LEGACY_IMPORT=ON \
+ -DCMAKE_EXE_LINKER_FLAGS="-Wl,--allow-multiple-definition" \
+ -DCMAKE_SHARED_LINKER_FLAGS="-Wl,--allow-multiple-definition" \
+ -DENABLE_TEST=OFF \
+ -DDOWNLOAD_GTEST=OFF \
+ -DBUILD_GTEST=OFF \
+ -DCMAKE_C_COMPILER=gcc \
+ -DCMAKE_CXX_COMPILER=g++ \
+ -DCMAKE_INSTALL_PREFIX="${NNCC_INSTALL_PREFIX}" \
+ -DCMAKE_BUILD_TYPE=release \
+ -DBUILD_WHITELIST=$(join_by ";" "${REQUIRED_UNITS[@]}") \
+ -DEXTERNALS_BUILD_THREADS=$((NPROC/2)) \
+ ${EXTRA_OPTIONS[@]} \
+ "${NNAS_PROJECT_PATH}/infra/nncc"
+}
+
+function preset_install()
+{
+ # Install libraries to bin/ for Windows release
+ mv ${NNCC_INSTALL_PREFIX}/lib/*.dll ${NNCC_INSTALL_PREFIX}/bin
+ rm -rf ${NNCC_INSTALL_PREFIX}/lib
+
+ # Install tf2nnpkg
+ install -T -m 755 -D "${SCRIPT_PATH}/res/tf2nnpkg.${PRESET}" "${NNAS_INSTALL_PREFIX}/bin/tf2nnpkg"
+
+ # Though you have to install tensorflow to run 'tf2tfliteV2',
+ # tensorflow can't be installed in mingw. First, You can install tensorflow
+ # from Window native CMD(run as administrator) with python virtual environment.
+ # And, you must copy it to "${NNAS_INSTALL_PREFIX}/bin/venv"
+}
diff --git a/infra/packaging/res/tf2nnpkg.20230413 b/infra/packaging/res/tf2nnpkg.20230413
new file mode 100644
index 000000000..a7446e6fe
--- /dev/null
+++ b/infra/packaging/res/tf2nnpkg.20230413
@@ -0,0 +1,109 @@
+#!/bin/bash
+
+set -e
+
+ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
+
+command_exists() {
+ if [ "$#" -le 0 ]; then
+ return 1
+ fi
+ command -v "$@" > /dev/null 2>&1
+}
+
+usage()
+{
+ echo "Convert TensorFlow model to nnpackage."
+ echo "Usage: tf2nnpkg"
+ echo " --info <path/to/info>"
+ echo " --graphdef <path/to/pb>"
+ echo " -o <path/to/nnpkg/directory>"
+ echo " --v2 (optional) Use TF 2.x interface"
+ exit 255
+}
+
+TF_INTERFACE="--v1"
+
+# Parse command-line arguments
+#
+while [ "$#" -ne 0 ]; do
+ CUR="$1"
+
+ case $CUR in
+ '--help')
+ usage
+ ;;
+ '--info')
+ export INFO_FILE="$2"
+ shift 2
+ ;;
+ '--graphdef')
+ export GRAPHDEF_FILE="$2"
+ shift 2
+ ;;
+ '-o')
+ export OUTPUT_DIR="$2"
+ shift 2
+ ;;
+ '--v2')
+ TF_INTERFACE="--v2"
+ shift
+ ;;
+ *)
+ echo "${CUR}"
+ shift
+ ;;
+ esac
+done
+
+if [ -z ${GRAPHDEF_FILE} ] || [ ! -e ${GRAPHDEF_FILE} ]; then
+ echo "pb is not found. Please check --graphdef is correct."
+ exit 2
+fi
+
+if [ -z ${INFO_FILE} ] || [ ! -e ${INFO_FILE} ]; then
+ echo "info is not found. Please check --info is correct."
+ exit 2
+fi
+
+if [ -z ${OUTPUT_DIR} ]; then
+ echo "output directory is not specifed. Please check -o is correct.."
+ exit 2
+fi
+
+FILE_BASE=$(basename ${GRAPHDEF_FILE})
+MODEL_NAME="${FILE_BASE%.*}"
+TMPDIR=$(mktemp -d)
+trap "{ rm -rf $TMPDIR; }" EXIT
+
+# activate python virtual environment
+VIRTUALENV_LINUX="${ROOT}/bin/venv/bin/activate"
+VIRTUALENV_WINDOWS="${ROOT}/bin/venv/Scripts/activate"
+
+if [ -e ${VIRTUALENV_LINUX} ]; then
+ source ${VIRTUALENV_LINUX}
+elif [ -e ${VIRTUALENV_WINDOWS} ]; then
+ source ${VIRTUALENV_WINDOWS}
+fi
+
+# parse inputs, outputs from info file
+INPUT=$(awk -F, '/^input/ { print $2 }' ${INFO_FILE} | cut -d: -f1 | tr -d ' ' | paste -d, -s)
+OUTPUT=$(awk -F, '/^output/ { print $2 }' ${INFO_FILE} | cut -d: -f1 | tr -d ' ' | paste -d, -s)
+
+INPUT_SHAPES=$(grep ^input ${INFO_FILE} | cut -d "[" -f2 | cut -d "]" -f1 | tr -d ' ' | xargs | tr ' ' ':')
+
+ONE_IMPORT_BCQ_SCRIPT="${ROOT}/bin/one-import-bcq ${TF_INTERFACE} "
+ONE_IMPORT_BCQ_SCRIPT+="-i ${GRAPHDEF_FILE} "
+ONE_IMPORT_BCQ_SCRIPT+="-o ${TMPDIR}/${MODEL_NAME}.tmp.circle "
+ONE_IMPORT_BCQ_SCRIPT+="-I ${INPUT} "
+ONE_IMPORT_BCQ_SCRIPT+="-O ${OUTPUT} "
+if [ ! -z ${INPUT_SHAPES} ]; then
+ ONE_IMPORT_BCQ_SCRIPT+="-s ${INPUT_SHAPES} "
+fi
+
+${ONE_IMPORT_BCQ_SCRIPT}
+
+# optimize
+"${ROOT}/bin/circle2circle" --resolve_customop_add "${TMPDIR}/${MODEL_NAME}.tmp.circle" "${TMPDIR}/${MODEL_NAME}.circle"
+
+"${ROOT}/bin/model2nnpkg" -o "${OUTPUT_DIR}" -m "${TMPDIR}/${MODEL_NAME}.circle"
diff --git a/infra/packaging/res/tf2nnpkg.20230907 b/infra/packaging/res/tf2nnpkg.20230907
new file mode 100644
index 000000000..a7446e6fe
--- /dev/null
+++ b/infra/packaging/res/tf2nnpkg.20230907
@@ -0,0 +1,109 @@
+#!/bin/bash
+
+set -e
+
+ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
+
+command_exists() {
+ if [ "$#" -le 0 ]; then
+ return 1
+ fi
+ command -v "$@" > /dev/null 2>&1
+}
+
+usage()
+{
+ echo "Convert TensorFlow model to nnpackage."
+ echo "Usage: tf2nnpkg"
+ echo " --info <path/to/info>"
+ echo " --graphdef <path/to/pb>"
+ echo " -o <path/to/nnpkg/directory>"
+ echo " --v2 (optional) Use TF 2.x interface"
+ exit 255
+}
+
+TF_INTERFACE="--v1"
+
+# Parse command-line arguments
+#
+while [ "$#" -ne 0 ]; do
+ CUR="$1"
+
+ case $CUR in
+ '--help')
+ usage
+ ;;
+ '--info')
+ export INFO_FILE="$2"
+ shift 2
+ ;;
+ '--graphdef')
+ export GRAPHDEF_FILE="$2"
+ shift 2
+ ;;
+ '-o')
+ export OUTPUT_DIR="$2"
+ shift 2
+ ;;
+ '--v2')
+ TF_INTERFACE="--v2"
+ shift
+ ;;
+ *)
+ echo "${CUR}"
+ shift
+ ;;
+ esac
+done
+
+if [ -z ${GRAPHDEF_FILE} ] || [ ! -e ${GRAPHDEF_FILE} ]; then
+ echo "pb is not found. Please check --graphdef is correct."
+ exit 2
+fi
+
+if [ -z ${INFO_FILE} ] || [ ! -e ${INFO_FILE} ]; then
+ echo "info is not found. Please check --info is correct."
+ exit 2
+fi
+
+if [ -z ${OUTPUT_DIR} ]; then
+ echo "output directory is not specifed. Please check -o is correct.."
+ exit 2
+fi
+
+FILE_BASE=$(basename ${GRAPHDEF_FILE})
+MODEL_NAME="${FILE_BASE%.*}"
+TMPDIR=$(mktemp -d)
+trap "{ rm -rf $TMPDIR; }" EXIT
+
+# activate python virtual environment
+VIRTUALENV_LINUX="${ROOT}/bin/venv/bin/activate"
+VIRTUALENV_WINDOWS="${ROOT}/bin/venv/Scripts/activate"
+
+if [ -e ${VIRTUALENV_LINUX} ]; then
+ source ${VIRTUALENV_LINUX}
+elif [ -e ${VIRTUALENV_WINDOWS} ]; then
+ source ${VIRTUALENV_WINDOWS}
+fi
+
+# parse inputs, outputs from info file
+INPUT=$(awk -F, '/^input/ { print $2 }' ${INFO_FILE} | cut -d: -f1 | tr -d ' ' | paste -d, -s)
+OUTPUT=$(awk -F, '/^output/ { print $2 }' ${INFO_FILE} | cut -d: -f1 | tr -d ' ' | paste -d, -s)
+
+INPUT_SHAPES=$(grep ^input ${INFO_FILE} | cut -d "[" -f2 | cut -d "]" -f1 | tr -d ' ' | xargs | tr ' ' ':')
+
+ONE_IMPORT_BCQ_SCRIPT="${ROOT}/bin/one-import-bcq ${TF_INTERFACE} "
+ONE_IMPORT_BCQ_SCRIPT+="-i ${GRAPHDEF_FILE} "
+ONE_IMPORT_BCQ_SCRIPT+="-o ${TMPDIR}/${MODEL_NAME}.tmp.circle "
+ONE_IMPORT_BCQ_SCRIPT+="-I ${INPUT} "
+ONE_IMPORT_BCQ_SCRIPT+="-O ${OUTPUT} "
+if [ ! -z ${INPUT_SHAPES} ]; then
+ ONE_IMPORT_BCQ_SCRIPT+="-s ${INPUT_SHAPES} "
+fi
+
+${ONE_IMPORT_BCQ_SCRIPT}
+
+# optimize
+"${ROOT}/bin/circle2circle" --resolve_customop_add "${TMPDIR}/${MODEL_NAME}.tmp.circle" "${TMPDIR}/${MODEL_NAME}.circle"
+
+"${ROOT}/bin/model2nnpkg" -o "${OUTPUT_DIR}" -m "${TMPDIR}/${MODEL_NAME}.circle"
diff --git a/infra/scripts/compiler_modules.sh b/infra/scripts/compiler_modules.sh
index 55e48f489..8b361a7ea 100644
--- a/infra/scripts/compiler_modules.sh
+++ b/infra/scripts/compiler_modules.sh
@@ -11,7 +11,7 @@ DEBUG_BUILD_ITEMS+=";oops;pepper-assert;pepper-csv2vec"
DEBUG_BUILD_ITEMS+=";hermes;hermes-std"
DEBUG_BUILD_ITEMS+=";loco;locop;locomotiv;logo-core;logo"
DEBUG_BUILD_ITEMS+=";foder;crew;souschef;arser;vconone"
-DEBUG_BUILD_ITEMS+=";safemain;mio-circle04;mio-tflite280;dio-hdf5"
+DEBUG_BUILD_ITEMS+=";safemain;mio-circle05;mio-tflite280;mio-circle06;mio-tflite2121;dio-hdf5"
DEBUG_BUILD_ITEMS+=";luci-compute"
DEBUG_BUILD_ITEMS+=";tflite2circle"
DEBUG_BUILD_ITEMS+=";luci"
@@ -35,3 +35,4 @@ DEBUG_BUILD_ITEMS+=";circle-operator-test"
DEBUG_BUILD_ITEMS+=";circle-interpreter;circle-interpreter-test"
DEBUG_BUILD_ITEMS+=";dalgona;dalgona-test"
DEBUG_BUILD_ITEMS+=";visq"
+DEBUG_BUILD_ITEMS+=";circle-mpqsolver"
diff --git a/infra/scripts/docker_build_nncc.sh b/infra/scripts/docker_build_nncc.sh
index 2e603b550..dd9d0bd9b 100755
--- a/infra/scripts/docker_build_nncc.sh
+++ b/infra/scripts/docker_build_nncc.sh
@@ -67,7 +67,7 @@ tar -zcf ${ARCHIVE_PATH}/nncc-test-package.tar.gz -C ${NNCC_INSTALL_PREFIX} ./te
if [ -z ${RELEASE_VERSION} ] || [ ${RELEASE_VERSION} == "nightly" ]; then
./nncc docker-run /bin/bash -c \
- 'dch -v $($(pwd)/tools/release_tool/onert_version.sh)~$(date "+%y%m%d%H") "nightly release" -D $(lsb_release --short --codename)'
+ 'dch -v $(${PWD}/${NNCC_INSTALL_PREFIX}/bin/one-version)~$(date "+%y%m%d%H") "nightly release" -D $(lsb_release --short --codename)'
./nncc docker-run dch -r ''
fi
diff --git a/infra/scripts/docker_collect_nnpkg_resources.sh b/infra/scripts/docker_collect_nnpkg_resources.sh
index 9fb7def56..8a73dd380 100755
--- a/infra/scripts/docker_collect_nnpkg_resources.sh
+++ b/infra/scripts/docker_collect_nnpkg_resources.sh
@@ -73,7 +73,7 @@ REQUIRED_UNITS+=("luci-compute")
# Circle compiler library (.circle -> .circle)
REQUIRED_UNITS+=("luci")
# Flatbuffer I/O
-REQUIRED_UNITS+=("mio-tflite280" "mio-circle04")
+REQUIRED_UNITS+=("mio-tflite280" "mio-circle05" "mio-tflite2121" "mio-circle06")
# Tools
REQUIRED_UNITS+=("tflite2circle" "circle2circle" "luci-interpreter")
REQUIRED_UNITS+=("souschef" "tflchef" "circlechef" "circle-verify")
diff --git a/nnpackage/schema/circle_schema.fbs b/nnpackage/schema/circle_schema.fbs
index 8ad444d95..cdc10361b 100644
--- a/nnpackage/schema/circle_schema.fbs
+++ b/nnpackage/schema/circle_schema.fbs
@@ -1,4 +1,4 @@
-// Copyright (c) 2019~2022 Samsung Electronics Co., Ltd. All Rights Reserved
+// Copyright (c) 2019~2023 Samsung Electronics Co., Ltd. All Rights Reserved
// Copyright 2017 The TensorFlow Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -29,6 +29,8 @@
// Version 0.2: BCQ_GATHER and BCQ_FULLY_CONNECTED are added.
// Version 0.3: SHUFFLED16x1FLOAT32 is added.
// Version 0.4: Base up to TensorFlow Lite v2.7.0 schema.
+// Version 0.5: Base up to TensorFlow Lite v2.10.1 schema.
+// Version 0.6: Base up to TensorFlow Lite v2.13.0 schema.
namespace circle;
@@ -61,6 +63,8 @@ enum TensorType : byte {
RESOURCE = 13,
VARIANT = 14,
UINT32 = 15,
+ UINT16 = 16,
+ INT4 = 17,
}
// Custom quantization parameters for experimenting with new quantization
@@ -200,6 +204,16 @@ table SparsityParameters {
dim_metadata:[DimensionMetadata];
}
+// The nested tensor type for VARIANT type.
+table VariantSubType {
+ // The tensor shape.
+ shape:[int];
+ type:TensorType;
+ // If false, the rank or the number of tensor dimensions is unknown.
+ // If false, "shape" must be [].
+ has_rank: bool = false;
+}
+
table Tensor {
// The tensor shape. The meaning of each entry is operator-specific but
// builtin ops use: [batch size, height, width, number of channels] (That's
@@ -227,6 +241,16 @@ table Tensor {
// Encodes `shape` with unknown dimensions. Unknown dimensions are
// represented with -1.
shape_signature:[int]; // Optional.
+
+ // If false, the rank or the number of tensor dimensions is unknown.
+ // If false, "shape" must be [].
+ has_rank: bool = false;
+
+ // The nested Tensor types for VARIANT type. This is always empty for
+ // non-VARIANT types. This is optional because the nested type can be omitted.
+ // Currently only 1 subtype is supported. The field is defined as an array for
+ // flexibility of supporting multiple subtypes in the future.
+ variant_tensors:[VariantSubType];
}
// A list of builtin operators. Builtin operators are slightly faster than custom
@@ -391,6 +415,21 @@ enum BuiltinOperator : int32 {
ASSIGN_VARIABLE = 144,
BROADCAST_ARGS = 145,
RANDOM_STANDARD_NORMAL = 146,
+ BUCKETIZE = 147,
+ RANDOM_UNIFORM = 148,
+ MULTINOMIAL = 149,
+ GELU = 150,
+ DYNAMIC_UPDATE_SLICE = 151,
+ RELU_0_TO_1 = 152,
+ UNSORTED_SEGMENT_PROD = 153,
+ UNSORTED_SEGMENT_MAX = 154,
+ UNSORTED_SEGMENT_SUM = 155,
+ ATAN2 = 156,
+ UNSORTED_SEGMENT_MIN = 157,
+ SIGN = 158,
+ BITCAST = 159,
+ BITWISE_XOR = 160,
+ RIGHT_SHIFT = 161,
}
// LINT.ThenChange(nnapi_linter/linter.proto)
@@ -510,6 +549,18 @@ union BuiltinOptions {
ReadVariableOptions,
AssignVariableOptions,
RandomOptions,
+ BucketizeOptions,
+ GeluOptions,
+ DynamicUpdateSliceOptions,
+ UnsortedSegmentProdOptions,
+ UnsortedSegmentMaxOptions,
+ UnsortedSegmentMinOptions,
+ UnsortedSegmentSumOptions,
+ ATan2Options,
+ SignOptions,
+ BitcastOptions,
+ BitwiseXorOptions,
+ RightShiftOptions,
BCQGatherOptions = 252,
BCQFullyConnectedOptions = 253,
InstanceNormOptions = 254,
@@ -704,8 +755,11 @@ table UnidirectionalSequenceLSTMOptions {
// If true then first dimension is sequence, otherwise batch.
time_major:bool;
- // Parameter for Unidirectional Sequence LSTM version 4.
+ // Parameter for Unidirectional Sequence LSTM version 3.
asymmetric_quantize_inputs:bool;
+
+ // Parameter for unidirectional sequence RNN version 4.
+ diagonal_recurrent_tensors:bool;
}
table BidirectionalSequenceLSTMOptions {
@@ -884,9 +938,13 @@ table SliceOptions {
}
table TransposeConvOptions {
+ // Parameters supported by version 1, 2, 3:
padding:Padding;
stride_w:int;
stride_h:int;
+
+ // Parameters supported by version 4:
+ fused_activation_function:ActivationFunctionType = NONE;
}
table ExpandDimsOptions {
@@ -1100,8 +1158,46 @@ table AssignVariableOptions {
}
table RandomOptions {
- seed: int;
- seed2: int;
+ seed: long;
+ seed2: long;
+}
+
+table BucketizeOptions {
+ boundaries: [float]; // The bucket boundaries.
+}
+
+table GeluOptions {
+ approximate: bool;
+}
+
+table DynamicUpdateSliceOptions {
+}
+
+table UnsortedSegmentProdOptions {
+}
+
+table UnsortedSegmentMaxOptions {
+}
+
+table UnsortedSegmentSumOptions {
+}
+
+table ATan2Options {
+}
+
+table UnsortedSegmentMinOptions{
+}
+
+table SignOptions {
+}
+
+table BitcastOptions {
+}
+
+table BitwiseXorOptions {
+}
+
+table RightShiftOptions {
}
table BCQGatherOptions {
diff --git a/onert-micro/CMakeLists.txt b/onert-micro/CMakeLists.txt
index d5ea95d51..416281d0f 100644
--- a/onert-micro/CMakeLists.txt
+++ b/onert-micro/CMakeLists.txt
@@ -7,33 +7,49 @@ find_program(ARM_C_COMPILER_PATH ${ARM_C_COMPILER})
if (NOT ARM_C_COMPILER_PATH)
message(STATUS "Build luci-micro: FALSE(ARM compiler is NOT FOUND)")
- return()
endif ()
-nnas_find_package(FlatBuffers EXACT 2.0 QUIET)
-
-if (NOT FlatBuffers_FOUND)
- message(STATUS "Build luci-micro: FALSE(FlatBuffers 2.0 NOT FOUND)")
- return()
-endif (NOT FlatBuffers_FOUND)
-
-message(STATUS "Build luci-micro: TRUE")
+if (NOT_BUILD_EXTERNALS)
+ message(STATUS "USE LOCAL EXTERNAL")
-set(SCHEMA_FILE "${NNAS_PROJECT_SOURCE_DIR}/res/CircleSchema/0.4/circle_schema.fbs")
+ set(ONERT_MICRO_EXTERNAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/externals")
+ set(Flatbuffers_DIR "${ONERT_MICRO_EXTERNAL_DIR}")
+ set(FlatBuffersSource_DIR "${Flatbuffers_DIR}")
+ set (EXT_OVERLAY_DIR "${ONERT_MICRO_EXTERNAL_DIR}")
+ set(GENERATED_INCLUDE_DIR "${ONERT_MICRO_EXTERNAL_DIR}/gen")
-# NOTE Copy circle_schema.fbs as schema.fbs to generate "schema_generated.fbs" instead of "circle_schema_generated.fbs"
-add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/schema.fbs"
- COMMAND ${CMAKE_COMMAND} -E copy "${SCHEMA_FILE}" schema.fbs
- WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
- DEPENDS "${SCHEMA_FILE}"
- )
-
-FlatBuffers_Target(luci_micro_circle_schema
- OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/gen/circle-generated/circle"
- INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/gen"
- SCHEMA_DIR "${CMAKE_CURRENT_BINARY_DIR}"
- SCHEMA_FILES "schema.fbs"
- )
+ add_subdirectory(externals)
+else()
+ message(STATUS "DOWNLOAD AND BUILD EXTERNALS")
+
+ nnas_find_package(FlatBuffers EXACT 2.0 QUIET)
+
+ if (NOT FlatBuffers_FOUND)
+ message(STATUS "Build luci-micro: FALSE(FlatBuffers 2.0 NOT FOUND)")
+ return()
+ endif (NOT FlatBuffers_FOUND)
+
+ message(STATUS "Build luci-micro: TRUE")
+
+ set(SCHEMA_FILE "${NNAS_PROJECT_SOURCE_DIR}/res/CircleSchema/0.4/circle_schema.fbs")
+
+ # NOTE Copy circle_schema.fbs as schema.fbs to generate "schema_generated.fbs" instead of "circle_schema_generated.fbs"
+ add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/schema.fbs"
+ COMMAND ${CMAKE_COMMAND} -E copy "${SCHEMA_FILE}" schema.fbs
+ WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
+ DEPENDS "${SCHEMA_FILE}"
+ )
+
+ FlatBuffers_Target(luci_micro_circle_schema
+ OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/gen/circle-generated/circle"
+ INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/gen"
+ SCHEMA_DIR "${CMAKE_CURRENT_BINARY_DIR}"
+ SCHEMA_FILES "schema.fbs"
+ )
+ set(Flatbuffers_DIR "${CMAKE_CURRENT_BINARY_DIR}/../../overlay/lib/cmake/flatbuffers")
+ set (EXT_OVERLAY_DIR "${CMAKE_CURRENT_BINARY_DIR}/../../overlay")
+ set(GENERATED_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/gen")
+endif()
set(LUCI_INTERPRETER_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/luci-interpreter/include")
add_subdirectory(luci-interpreter/src/core/reader)
@@ -70,8 +86,9 @@ set(CMAKE_ARM_OPTIONS
-DBUILD_CMSIS_NN_FUNCTIONS=ON
-DTARGET_CPU=${TARGET_CPU}
-DTARGET_ARCH=${TARGET_ARCH}
- "-DEXT_OVERLAY_DIR=${CMAKE_CURRENT_BINARY_DIR}/../../overlay"
- "-DFlatbuffers_DIR=${CMAKE_CURRENT_BINARY_DIR}/../../overlay/lib/cmake/flatbuffers"
+ "-DEXT_OVERLAY_DIR=${EXT_OVERLAY_DIR}"
+ "-DFlatbuffers_DIR=${Flatbuffers_DIR}"
+ "-DFlatBuffersSource_DIR=${FlatBuffersSource_DIR}"
"-DCMAKE_TOOLCHAIN_FILE=${NNAS_PROJECT_SOURCE_DIR}/infra/onert-micro/cmake/buildtool/config/arm-none-eabi-gcc.cmake"
"-DLUCI_INTERPRETER_PAL_DIR=${LUCI_INTERPRETER_PAL_DIR}"
"-DNNAS_PROJECT_SOURCE_DIR=${NNAS_PROJECT_SOURCE_DIR}"
@@ -85,7 +102,7 @@ set(CMAKE_ARM_OPTIONS
-DBUILD_GTEST=OFF
"-DNNAS_ROOT=${NNAS_PROJECT_SOURCE_DIR}"
-DENABLE_STRICT_BUILD=OFF
- "-DGENERATED_INCLUDE_DIR=${CMAKE_CURRENT_BINARY_DIR}/gen"
+ "-DGENERATED_INCLUDE_DIR=${GENERATED_INCLUDE_DIR}"
)
if (GENERATE_KERNELS_LIST_FROM)
@@ -93,6 +110,17 @@ if (GENERATE_KERNELS_LIST_FROM)
list(APPEND CMAKE_ARM_OPTIONS "-DLUCI_INTERPRETER_KERNELS_BUILD_LIST=${GENERATED_KERNELS_LIST_PATH}")
endif ()
+if (NOT_BUILD_EXTERNALS)
+ list(APPEND CMAKE_ARM_OPTIONS "-DNOT_BUILD_EXTERNALS=ON")
+else()
+ list(APPEND CMAKE_ARM_OPTIONS "-DNOT_BUILD_EXTERNALS=OFF")
+endif ()
+
+if (ENABLE_ONERT_MICRO_TEST)
+ message(STATUS "Enable tests")
+ list(APPEND CMAKE_ARM_OPTIONS "-DENABLE_TEST=ON")
+endif ()
+
if (DIS_QUANT)
message(STATUS "ONERT-MICRO will not use part for QUANTIZED models")
add_definitions(-DDIS_QUANT)
@@ -105,6 +133,11 @@ if (DIS_FLOAT)
list(APPEND CMAKE_ARM_OPTIONS "-DDIS_FLOAT=ON")
endif()
+if (DIS_DYN_SHAPES)
+ message(STATUS "ONERT-MICRO will not use dynamic shapes")
+ add_definitions(-DDIS_DYN_SHAPES)
+endif()
+
set(MICRO_ARM_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/standalone_arm")
file(MAKE_DIRECTORY "${MICRO_ARM_BUILD_DIR}")
@@ -145,6 +178,8 @@ unset(KERNELS CACHE)
unset(USE_STATIC_KERNEL CACHE)
unset(DIS_QUANT CACHE)
unset(DIS_FLOAT CACHE)
+unset(ENABLE_ONERT_MICRO_TEST CACHE)
+unset(NOT_BUILD_EXTERNALS CACHE)
set(MICRO_ARM_BINARY "${MICRO_ARM_BUILD_DIR}/luci-interpreter/src/libluci_interpreter_micro.a")
diff --git a/onert-micro/README.md b/onert-micro/README.md
index 6641ad7a7..062dbdb79 100644
--- a/onert-micro/README.md
+++ b/onert-micro/README.md
@@ -1,10 +1,10 @@
-# luci-micro
+# onert-micro
-`luci-micro` is MCU specialized build of luci-interpreter with several benchmark applications.
+`onert-micro`(a.k.a `luci-micro`) is MCU specialized build of luci-interpreter with several benchmark applications.
## Contents
-Luci-micro contains cmake infrastructure to build:
+onert-micro contains cmake infrastructure to build:
- stand-alone interpreter library
- benchmark applications using luci interpreter on arm MCUs
@@ -29,18 +29,10 @@ $ sudo apt-get install gcc-arm-none-eabi
$ cd <path to ONE>
$ mkdir build
# cd build
-$ cmake ../infra/nncc
+$ cmake ../infra/onert-micro
$ make -j$(nproc) luci_interpreter_micro_arm
```
-**nncc script build**
-
-``` bash
-$ cd <path to ONE>
-$ ./nncc configure
-$ ./nncc build -j$(nproc) luci_interpreter_micro_arm
-```
-
### Known issues
Interpreter uses TensorFlow headers that produces warnings.
@@ -53,4 +45,84 @@ but some old arm compilers have issues with it:
## How to use
-TBD
+### Convert tflite model to circle model
+
+To inference with tflite model, you need to convert it to circle model format(https://github.com/Samsung/ONE/blob/master/res/CircleSchema/0.4/circle_schema.fbs).
+Please refer to `tflite2circle` tool(https://github.com/Samsung/ONE/tree/master/compiler/tflite2circle) for this purpose.
+
+### Convert to c array model
+
+Many MCU platforms are lack of file system support. The proper way to provide a model to onert-micro is to convert it into c array so that it can be compiled into MCU binary.
+
+``` bash
+xxi -i model.circle > model.h
+```
+
+Then, model.h looks like this:
+
+``` cpp
+unsigned char model_circle[] = {
+ 0x22, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x0e, 0x00,
+ // .....
+};
+unsigned int model_circle_len = 1004;
+```
+
+### API
+
+Once you have c array model, you are ready to use onert-micro.
+
+To run a model with onert-micro, follow the instruction:
+
+1. Include onert-micro header
+
+``` cpp
+#include <luci_interpreter/Interpreter.h>
+```
+
+2. Create interpreter instance
+
+onert-micro interpreter expects model as c array as mentioned in [Previous Section](#convert-to-c-array-model).
+
+``` cpp
+#include "model.h"
+
+luci_interpreter::Interpreter interpreter(model_circle, true);
+```
+
+3. Feed input data
+
+To feed input data into interpreter, we need to do two steps: 1) allocate input tensors and 2) copy input into input tensors.
+
+``` cpp
+ for (int32_t i = 0; i < num_inputs; i++)
+ {
+ auto input_data = reinterpret_cast<char *>(interpreter.allocateInputTensor(i));
+ readDataFromFile(std::string(input_prefix) + std::to_string(i), input_data,
+ interpreter.getInputDataSizeByIndex(i));
+ }
+```
+
+4. Do inference
+
+``` cpp
+ interpreter.interpret();
+```
+
+5. Get output data
+
+``` cpp
+ auto data = interpreter.readOutputTensor(i);
+```
+
+
+### Reduce Binary Size
+
+onert-micro provides compile flags to generate reduced-size binary.
+
+- `DIS_QUANT` : Flag for Disabling Quantized Type Operation
+- `DIS_FLOAT` : Flag for Disabling Float Operation
+- `DIS_DYN_SHAPES` : Flag for Disabling Dynamic Shape Support
+
+Also, you can build onert-micro library only with kernels in target models.
+For this, please remove all the kernels from [KernelsToBuild.lst](./luci-interpreter/pal/mcu/KernelsToBuild.lst) except kernels in your target model.
diff --git a/onert-micro/eval-driver/Driver.cpp b/onert-micro/eval-driver/Driver.cpp
index 7ec4219f4..d29c41da3 100644
--- a/onert-micro/eval-driver/Driver.cpp
+++ b/onert-micro/eval-driver/Driver.cpp
@@ -94,7 +94,7 @@ int entry(int argc, char **argv)
}
// Create interpreter.
- luci_interpreter::Interpreter interpreter(model_data.data());
+ luci_interpreter::Interpreter interpreter(model_data.data(), true);
// Set input.
// Data for n'th input is read from ${input_prefix}n
diff --git a/onert-micro/externals/CMakeLists.txt b/onert-micro/externals/CMakeLists.txt
new file mode 100644
index 000000000..221001cfe
--- /dev/null
+++ b/onert-micro/externals/CMakeLists.txt
@@ -0,0 +1,9 @@
+unset(OUTPUT_FILES)
+set(OUTPUT_FILES "${ONERT_MICRO_EXTERNAL_DIR}/gen/circle-generated/circle/schema_generated.h")
+set(TGT luci_micro_circle_schema)
+
+# NOTE This header-only library
+add_library(${TGT} STATIC ${OUTPUT_FILES})
+set_target_properties(${TGT} PROPERTIES LINKER_LANGUAGE CXX)
+target_include_directories(${TGT} PUBLIC "${ONERT_MICRO_EXTERNAL_DIR}/gen")
+target_include_directories(${TGT} PUBLIC "${ONERT_MICRO_EXTERNAL_DIR}")
diff --git a/onert-micro/externals/flatbuffers/base.h b/onert-micro/externals/flatbuffers/base.h
new file mode 100644
index 000000000..56bf9b427
--- /dev/null
+++ b/onert-micro/externals/flatbuffers/base.h
@@ -0,0 +1,453 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2017 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef FLATBUFFERS_BASE_H_
+#define FLATBUFFERS_BASE_H_
+
+// clang-format off
+
+// If activate should be declared and included first.
+#if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && \
+ defined(_MSC_VER) && defined(_DEBUG)
+ // The _CRTDBG_MAP_ALLOC inside <crtdbg.h> will replace
+ // calloc/free (etc) to its debug version using #define directives.
+ #define _CRTDBG_MAP_ALLOC
+ #include <stdlib.h>
+ #include <crtdbg.h>
+ // Replace operator new by trace-enabled version.
+ #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
+ #define new DEBUG_NEW
+#endif
+
+#if !defined(FLATBUFFERS_ASSERT)
+#include <assert.h>
+#define FLATBUFFERS_ASSERT assert
+#elif defined(FLATBUFFERS_ASSERT_INCLUDE)
+// Include file with forward declaration
+#include FLATBUFFERS_ASSERT_INCLUDE
+#endif
+
+#ifndef ARDUINO
+#include <cstdint>
+#endif
+
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+
+#if defined(ARDUINO) && !defined(ARDUINOSTL_M_H)
+ #include <utility.h>
+#else
+ #include <utility>
+#endif
+
+#include <string>
+#include <type_traits>
+#include <vector>
+#include <set>
+#include <algorithm>
+#include <iterator>
+#include <memory>
+
+#if defined(__unix__) && !defined(FLATBUFFERS_LOCALE_INDEPENDENT)
+ #include <unistd.h>
+#endif
+
+#ifdef _STLPORT_VERSION
+ #define FLATBUFFERS_CPP98_STL
+#endif
+
+#ifdef __ANDROID__
+ #include <android/api-level.h>
+#endif
+
+#if defined(__ICCARM__)
+#include <intrinsics.h>
+#endif
+
+// Note the __clang__ check is needed, because clang presents itself
+// as an older GNUC compiler (4.2).
+// Clang 3.3 and later implement all of the ISO C++ 2011 standard.
+// Clang 3.4 and later implement all of the ISO C++ 2014 standard.
+// http://clang.llvm.org/cxx_status.html
+
+// Note the MSVC value '__cplusplus' may be incorrect:
+// The '__cplusplus' predefined macro in the MSVC stuck at the value 199711L,
+// indicating (erroneously!) that the compiler conformed to the C++98 Standard.
+// This value should be correct starting from MSVC2017-15.7-Preview-3.
+// The '__cplusplus' will be valid only if MSVC2017-15.7-P3 and the `/Zc:__cplusplus` switch is set.
+// Workaround (for details see MSDN):
+// Use the _MSC_VER and _MSVC_LANG definition instead of the __cplusplus for compatibility.
+// The _MSVC_LANG macro reports the Standard version regardless of the '/Zc:__cplusplus' switch.
+
+#if defined(__GNUC__) && !defined(__clang__)
+ #define FLATBUFFERS_GCC (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+#else
+ #define FLATBUFFERS_GCC 0
+#endif
+
+#if defined(__clang__)
+ #define FLATBUFFERS_CLANG (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
+#else
+ #define FLATBUFFERS_CLANG 0
+#endif
+
+/// @cond FLATBUFFERS_INTERNAL
+#if __cplusplus <= 199711L && \
+ (!defined(_MSC_VER) || _MSC_VER < 1600) && \
+ (!defined(__GNUC__) || \
+ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40400))
+ #error A C++11 compatible compiler with support for the auto typing is \
+ required for FlatBuffers.
+ #error __cplusplus _MSC_VER __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__
+#endif
+
+#if !defined(__clang__) && \
+ defined(__GNUC__) && \
+ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40600)
+ // Backwards compatibility for g++ 4.4, and 4.5 which don't have the nullptr
+ // and constexpr keywords. Note the __clang__ check is needed, because clang
+ // presents itself as an older GNUC compiler.
+ #ifndef nullptr_t
+ const class nullptr_t {
+ public:
+ template<class T> inline operator T*() const { return 0; }
+ private:
+ void operator&() const;
+ } nullptr = {};
+ #endif
+ #ifndef constexpr
+ #define constexpr const
+ #endif
+#endif
+
+// The wire format uses a little endian encoding (since that's efficient for
+// the common platforms).
+#if defined(__s390x__)
+ #define FLATBUFFERS_LITTLEENDIAN 0
+#endif // __s390x__
+#if !defined(FLATBUFFERS_LITTLEENDIAN)
+ #if defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__)
+ #if (defined(__BIG_ENDIAN__) || \
+ (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
+ #define FLATBUFFERS_LITTLEENDIAN 0
+ #else
+ #define FLATBUFFERS_LITTLEENDIAN 1
+ #endif // __BIG_ENDIAN__
+ #elif defined(_MSC_VER)
+ #if defined(_M_PPC)
+ #define FLATBUFFERS_LITTLEENDIAN 0
+ #else
+ #define FLATBUFFERS_LITTLEENDIAN 1
+ #endif
+ #else
+ #error Unable to determine endianness, define FLATBUFFERS_LITTLEENDIAN.
+ #endif
+#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
+
+#define FLATBUFFERS_VERSION_MAJOR 2
+#define FLATBUFFERS_VERSION_MINOR 0
+#define FLATBUFFERS_VERSION_REVISION 0
+#define FLATBUFFERS_STRING_EXPAND(X) #X
+#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
+namespace flatbuffers {
+ // Returns version as string "MAJOR.MINOR.REVISION".
+ const char* FLATBUFFERS_VERSION();
+}
+
+#if (!defined(_MSC_VER) || _MSC_VER > 1600) && \
+ (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 407)) || \
+ defined(__clang__)
+ #define FLATBUFFERS_FINAL_CLASS final
+ #define FLATBUFFERS_OVERRIDE override
+ #define FLATBUFFERS_EXPLICIT_CPP11 explicit
+ #define FLATBUFFERS_VTABLE_UNDERLYING_TYPE : flatbuffers::voffset_t
+#else
+ #define FLATBUFFERS_FINAL_CLASS
+ #define FLATBUFFERS_OVERRIDE
+ #define FLATBUFFERS_EXPLICIT_CPP11
+ #define FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+#endif
+
+#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \
+ (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \
+ (defined(__cpp_constexpr) && __cpp_constexpr >= 200704)
+ #define FLATBUFFERS_CONSTEXPR constexpr
+ #define FLATBUFFERS_CONSTEXPR_CPP11 constexpr
+ #define FLATBUFFERS_CONSTEXPR_DEFINED
+#else
+ #define FLATBUFFERS_CONSTEXPR const
+ #define FLATBUFFERS_CONSTEXPR_CPP11
+#endif
+
+#if (defined(__cplusplus) && __cplusplus >= 201402L) || \
+ (defined(__cpp_constexpr) && __cpp_constexpr >= 201304)
+ #define FLATBUFFERS_CONSTEXPR_CPP14 FLATBUFFERS_CONSTEXPR_CPP11
+#else
+ #define FLATBUFFERS_CONSTEXPR_CPP14
+#endif
+
+#if (defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \
+ (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 190023026)) || \
+ defined(__clang__)
+ #define FLATBUFFERS_NOEXCEPT noexcept
+#else
+ #define FLATBUFFERS_NOEXCEPT
+#endif
+
+// NOTE: the FLATBUFFERS_DELETE_FUNC macro may change the access mode to
+// private, so be sure to put it at the end or reset access mode explicitly.
+#if (!defined(_MSC_VER) || _MSC_FULL_VER >= 180020827) && \
+ (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 404)) || \
+ defined(__clang__)
+ #define FLATBUFFERS_DELETE_FUNC(func) func = delete
+#else
+ #define FLATBUFFERS_DELETE_FUNC(func) private: func
+#endif
+
+#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \
+ (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)) || \
+ defined(__clang__)
+ #define FLATBUFFERS_DEFAULT_DECLARATION
+#endif
+
+// Check if we can use template aliases
+// Not possible if Microsoft Compiler before 2012
+// Possible is the language feature __cpp_alias_templates is defined well
+// Or possible if the C++ std is C+11 or newer
+#if (defined(_MSC_VER) && _MSC_VER > 1700 /* MSVC2012 */) \
+ || (defined(__cpp_alias_templates) && __cpp_alias_templates >= 200704) \
+ || (defined(__cplusplus) && __cplusplus >= 201103L)
+ #define FLATBUFFERS_TEMPLATES_ALIASES
+#endif
+
+#ifndef FLATBUFFERS_HAS_STRING_VIEW
+ // Only provide flatbuffers::string_view if __has_include can be used
+ // to detect a header that provides an implementation
+ #if defined(__has_include)
+ // Check for std::string_view (in c++17)
+ #if __has_include(<string_view>) && (__cplusplus >= 201606 || (defined(_HAS_CXX17) && _HAS_CXX17))
+ #include <string_view>
+ namespace flatbuffers {
+ typedef std::string_view string_view;
+ }
+ #define FLATBUFFERS_HAS_STRING_VIEW 1
+ // Check for std::experimental::string_view (in c++14, compiler-dependent)
+ #elif __has_include(<experimental/string_view>) && (__cplusplus >= 201411)
+ #include <experimental/string_view>
+ namespace flatbuffers {
+ typedef std::experimental::string_view string_view;
+ }
+ #define FLATBUFFERS_HAS_STRING_VIEW 1
+ // Check for absl::string_view
+ #elif __has_include("absl/strings/string_view.h")
+ #include "absl/strings/string_view.h"
+ namespace flatbuffers {
+ typedef absl::string_view string_view;
+ }
+ #define FLATBUFFERS_HAS_STRING_VIEW 1
+ #endif
+ #endif // __has_include
+#endif // !FLATBUFFERS_HAS_STRING_VIEW
+
+#ifndef FLATBUFFERS_HAS_NEW_STRTOD
+ // Modern (C++11) strtod and strtof functions are available for use.
+ // 1) nan/inf strings as argument of strtod;
+ // 2) hex-float as argument of strtod/strtof.
+ #if (defined(_MSC_VER) && _MSC_VER >= 1900) || \
+ (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)) || \
+ (defined(__clang__))
+ #define FLATBUFFERS_HAS_NEW_STRTOD 1
+ #endif
+#endif // !FLATBUFFERS_HAS_NEW_STRTOD
+
+#ifndef FLATBUFFERS_LOCALE_INDEPENDENT
+ // Enable locale independent functions {strtof_l, strtod_l,strtoll_l, strtoull_l}.
+ #if ((defined(_MSC_VER) && _MSC_VER >= 1800) || \
+ (defined(_XOPEN_VERSION) && (_XOPEN_VERSION>=700)) && (!defined(__ANDROID_API__) || (defined(__ANDROID_API__) && (__ANDROID_API__>=21))))
+ #define FLATBUFFERS_LOCALE_INDEPENDENT 1
+ #else
+ #define FLATBUFFERS_LOCALE_INDEPENDENT 0
+ #endif
+#endif // !FLATBUFFERS_LOCALE_INDEPENDENT
+
+// Suppress Undefined Behavior Sanitizer (recoverable only). Usage:
+// - __supress_ubsan__("undefined")
+// - __supress_ubsan__("signed-integer-overflow")
+#if defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >=7))
+ #define __supress_ubsan__(type) __attribute__((no_sanitize(type)))
+#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)
+ #define __supress_ubsan__(type) __attribute__((no_sanitize_undefined))
+#else
+ #define __supress_ubsan__(type)
+#endif
+
+// This is constexpr function used for checking compile-time constants.
+// Avoid `#pragma warning(disable: 4127) // C4127: expression is constant`.
+template<typename T> FLATBUFFERS_CONSTEXPR inline bool IsConstTrue(T t) {
+ return !!t;
+}
+
+// Enable C++ attribute [[]] if std:c++17 or higher.
+#if ((__cplusplus >= 201703L) \
+ || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L)))
+ // All attributes unknown to an implementation are ignored without causing an error.
+ #define FLATBUFFERS_ATTRIBUTE(attr) [[attr]]
+
+ #define FLATBUFFERS_FALLTHROUGH() [[fallthrough]]
+#else
+ #define FLATBUFFERS_ATTRIBUTE(attr)
+
+ #if FLATBUFFERS_CLANG >= 30800
+ #define FLATBUFFERS_FALLTHROUGH() [[clang::fallthrough]]
+ #elif FLATBUFFERS_GCC >= 70300
+ #define FLATBUFFERS_FALLTHROUGH() [[gnu::fallthrough]]
+ #else
+ #define FLATBUFFERS_FALLTHROUGH()
+ #endif
+#endif
+
+/// @endcond
+
+/// @file
+namespace flatbuffers {
+
+/// @cond FLATBUFFERS_INTERNAL
+// Our default offset / size type, 32bit on purpose on 64bit systems.
+// Also, using a consistent offset type maintains compatibility of serialized
+// offset values between 32bit and 64bit systems.
+typedef uint32_t uoffset_t;
+
+// Signed offsets for references that can go in both directions.
+typedef int32_t soffset_t;
+
+// Offset/index used in v-tables, can be changed to uint8_t in
+// format forks to save a bit of space if desired.
+typedef uint16_t voffset_t;
+
+typedef uintmax_t largest_scalar_t;
+
+// In 32bits, this evaluates to 2GB - 1
+#define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(::flatbuffers::soffset_t) * 8 - 1)) - 1)
+
+// We support aligning the contents of buffers up to this size.
+#define FLATBUFFERS_MAX_ALIGNMENT 16
+
+inline bool VerifyAlignmentRequirements(size_t align, size_t min_align = 1) {
+ return (min_align <= align) && (align <= (FLATBUFFERS_MAX_ALIGNMENT)) &&
+ (align & (align - 1)) == 0; // must be power of 2
+}
+
+#if defined(_MSC_VER)
+ #pragma warning(disable: 4351) // C4351: new behavior: elements of array ... will be default initialized
+ #pragma warning(push)
+ #pragma warning(disable: 4127) // C4127: conditional expression is constant
+#endif
+
+template<typename T> T EndianSwap(T t) {
+ #if defined(_MSC_VER)
+ #define FLATBUFFERS_BYTESWAP16 _byteswap_ushort
+ #define FLATBUFFERS_BYTESWAP32 _byteswap_ulong
+ #define FLATBUFFERS_BYTESWAP64 _byteswap_uint64
+ #elif defined(__ICCARM__)
+ #define FLATBUFFERS_BYTESWAP16 __REV16
+ #define FLATBUFFERS_BYTESWAP32 __REV
+ #define FLATBUFFERS_BYTESWAP64(x) \
+ ((__REV(static_cast<uint32_t>(x >> 32U))) | (static_cast<uint64_t>(__REV(static_cast<uint32_t>(x)))) << 32U)
+ #else
+ #if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ < 408 && !defined(__clang__)
+ // __builtin_bswap16 was missing prior to GCC 4.8.
+ #define FLATBUFFERS_BYTESWAP16(x) \
+ static_cast<uint16_t>(__builtin_bswap32(static_cast<uint32_t>(x) << 16))
+ #else
+ #define FLATBUFFERS_BYTESWAP16 __builtin_bswap16
+ #endif
+ #define FLATBUFFERS_BYTESWAP32 __builtin_bswap32
+ #define FLATBUFFERS_BYTESWAP64 __builtin_bswap64
+ #endif
+ if (sizeof(T) == 1) { // Compile-time if-then's.
+ return t;
+ } else if (sizeof(T) == 2) {
+ union { T t; uint16_t i; } u = { t };
+ u.i = FLATBUFFERS_BYTESWAP16(u.i);
+ return u.t;
+ } else if (sizeof(T) == 4) {
+ union { T t; uint32_t i; } u = { t };
+ u.i = FLATBUFFERS_BYTESWAP32(u.i);
+ return u.t;
+ } else if (sizeof(T) == 8) {
+ union { T t; uint64_t i; } u = { t };
+ u.i = FLATBUFFERS_BYTESWAP64(u.i);
+ return u.t;
+ } else {
+ FLATBUFFERS_ASSERT(0);
+ return t;
+ }
+}
+
+#if defined(_MSC_VER)
+ #pragma warning(pop)
+#endif
+
+
+template<typename T> T EndianScalar(T t) {
+ #if FLATBUFFERS_LITTLEENDIAN
+ return t;
+ #else
+ return EndianSwap(t);
+ #endif
+}
+
+template<typename T>
+// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details.
+__supress_ubsan__("alignment")
+T ReadScalar(const void *p) {
+ return EndianScalar(*reinterpret_cast<const T *>(p));
+}
+
+// See https://github.com/google/flatbuffers/issues/5950
+
+#if (FLATBUFFERS_GCC >= 100000) && (FLATBUFFERS_GCC < 110000)
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wstringop-overflow"
+#endif
+
+template<typename T>
+// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details.
+__supress_ubsan__("alignment")
+void WriteScalar(void *p, T t) {
+ *reinterpret_cast<T *>(p) = EndianScalar(t);
+}
+
+template<typename T> struct Offset;
+template<typename T> __supress_ubsan__("alignment") void WriteScalar(void *p, Offset<T> t) {
+ *reinterpret_cast<uoffset_t *>(p) = EndianScalar(t.o);
+}
+
+#if (FLATBUFFERS_GCC >= 100000) && (FLATBUFFERS_GCC < 110000)
+ #pragma GCC diagnostic pop
+#endif
+
+// Computes how many bytes you'd have to pad to be able to write an
+// "scalar_size" scalar if the buffer had grown to "buf_size" (downwards in
+// memory).
+__supress_ubsan__("unsigned-integer-overflow")
+inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) {
+ return ((~buf_size) + 1) & (scalar_size - 1);
+}
+
+} // namespace flatbuffers
+#endif // FLATBUFFERS_BASE_H_
diff --git a/onert-micro/externals/flatbuffers/code_generators.h b/onert-micro/externals/flatbuffers/code_generators.h
new file mode 100644
index 000000000..3908ea582
--- /dev/null
+++ b/onert-micro/externals/flatbuffers/code_generators.h
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2014 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLATBUFFERS_CODE_GENERATORS_H_
+#define FLATBUFFERS_CODE_GENERATORS_H_
+
+#include <map>
+#include <sstream>
+
+#include "flatbuffers/idl.h"
+
+namespace flatbuffers
+{
+
+// Utility class to assist in generating code through use of text templates.
+//
+// Example code:
+// CodeWriter code("\t");
+// code.SetValue("NAME", "Foo");
+// code += "void {{NAME}}() { printf("%s", "{{NAME}}"); }";
+// code.SetValue("NAME", "Bar");
+// code += "void {{NAME}}() { printf("%s", "{{NAME}}"); }";
+// std::cout << code.ToString() << std::endl;
+//
+// Output:
+// void Foo() { printf("%s", "Foo"); }
+// void Bar() { printf("%s", "Bar"); }
+class CodeWriter
+{
+public:
+ CodeWriter(std::string pad = std::string()) : pad_(pad), cur_ident_lvl_(0), ignore_ident_(false)
+ {
+ }
+
+ // Clears the current "written" code.
+ void Clear()
+ {
+ stream_.str("");
+ stream_.clear();
+ }
+
+ // Associates a key with a value. All subsequent calls to operator+=, where
+ // the specified key is contained in {{ and }} delimiters will be replaced by
+ // the given value.
+ void SetValue(const std::string &key, const std::string &value) { value_map_[key] = value; }
+
+ std::string GetValue(const std::string &key) const
+ {
+ const auto it = value_map_.find(key);
+ return it == value_map_.end() ? "" : it->second;
+ }
+
+ // Appends the given text to the generated code as well as a newline
+ // character. Any text within {{ and }} delimiters is replaced by values
+ // previously stored in the CodeWriter by calling SetValue above. The newline
+ // will be suppressed if the text ends with the \\ character.
+ void operator+=(std::string text);
+
+ // Returns the current contents of the CodeWriter as a std::string.
+ std::string ToString() const { return stream_.str(); }
+
+ // Increase ident level for writing code
+ void IncrementIdentLevel() { cur_ident_lvl_++; }
+ // Decrease ident level for writing code
+ void DecrementIdentLevel()
+ {
+ if (cur_ident_lvl_)
+ cur_ident_lvl_--;
+ }
+
+ void SetPadding(const std::string &padding) { pad_ = padding; }
+
+private:
+ std::map<std::string, std::string> value_map_;
+ std::stringstream stream_;
+ std::string pad_;
+ int cur_ident_lvl_;
+ bool ignore_ident_;
+
+ // Add ident padding (tab or space) based on ident level
+ void AppendIdent(std::stringstream &stream);
+};
+
+class BaseGenerator
+{
+public:
+ virtual bool generate() = 0;
+
+ static std::string NamespaceDir(const Parser &parser, const std::string &path,
+ const Namespace &ns, const bool dasherize = false);
+
+ static std::string ToDasherizedCase(const std::string pascal_case);
+
+ std::string GeneratedFileName(const std::string &path, const std::string &file_name,
+ const IDLOptions &options) const;
+
+protected:
+ BaseGenerator(const Parser &parser, const std::string &path, const std::string &file_name,
+ std::string qualifying_start, std::string qualifying_separator,
+ std::string default_extension)
+ : parser_(parser), path_(path), file_name_(file_name), qualifying_start_(qualifying_start),
+ qualifying_separator_(qualifying_separator), default_extension_(default_extension)
+ {
+ }
+ virtual ~BaseGenerator() {}
+
+ // No copy/assign.
+ BaseGenerator &operator=(const BaseGenerator &);
+ BaseGenerator(const BaseGenerator &);
+
+ std::string NamespaceDir(const Namespace &ns, const bool dasherize = false) const;
+
+ static const char *FlatBuffersGeneratedWarning();
+
+ static std::string FullNamespace(const char *separator, const Namespace &ns);
+
+ static std::string LastNamespacePart(const Namespace &ns);
+
+ // tracks the current namespace for early exit in WrapInNameSpace
+ // c++, java and csharp returns a different namespace from
+ // the following default (no early exit, always fully qualify),
+ // which works for js and php
+ virtual const Namespace *CurrentNameSpace() const { return nullptr; }
+
+ // Ensure that a type is prefixed with its namespace even within
+ // its own namespace to avoid conflict between generated method
+ // names and similarly named classes or structs
+ std::string WrapInNameSpace(const Namespace *ns, const std::string &name) const;
+
+ std::string WrapInNameSpace(const Definition &def) const;
+
+ std::string GetNameSpace(const Definition &def) const;
+
+ const Parser &parser_;
+ const std::string &path_;
+ const std::string &file_name_;
+ const std::string qualifying_start_;
+ const std::string qualifying_separator_;
+ const std::string default_extension_;
+};
+
+struct CommentConfig
+{
+ const char *first_line;
+ const char *content_line_prefix;
+ const char *last_line;
+};
+
+extern void GenComment(const std::vector<std::string> &dc, std::string *code_ptr,
+ const CommentConfig *config, const char *prefix = "");
+
+class FloatConstantGenerator
+{
+public:
+ virtual ~FloatConstantGenerator() {}
+ std::string GenFloatConstant(const FieldDef &field) const;
+
+private:
+ virtual std::string Value(double v, const std::string &src) const = 0;
+ virtual std::string Inf(double v) const = 0;
+ virtual std::string NaN(double v) const = 0;
+
+ virtual std::string Value(float v, const std::string &src) const = 0;
+ virtual std::string Inf(float v) const = 0;
+ virtual std::string NaN(float v) const = 0;
+
+ template <typename T> std::string GenFloatConstantImpl(const FieldDef &field) const;
+};
+
+class SimpleFloatConstantGenerator : public FloatConstantGenerator
+{
+public:
+ SimpleFloatConstantGenerator(const char *nan_number, const char *pos_inf_number,
+ const char *neg_inf_number);
+
+private:
+ std::string Value(double v, const std::string &src) const FLATBUFFERS_OVERRIDE;
+ std::string Inf(double v) const FLATBUFFERS_OVERRIDE;
+ std::string NaN(double v) const FLATBUFFERS_OVERRIDE;
+
+ std::string Value(float v, const std::string &src) const FLATBUFFERS_OVERRIDE;
+ std::string Inf(float v) const FLATBUFFERS_OVERRIDE;
+ std::string NaN(float v) const FLATBUFFERS_OVERRIDE;
+
+ const std::string nan_number_;
+ const std::string pos_inf_number_;
+ const std::string neg_inf_number_;
+};
+
+// C++, C#, Java like generator.
+class TypedFloatConstantGenerator : public FloatConstantGenerator
+{
+public:
+ TypedFloatConstantGenerator(const char *double_prefix, const char *single_prefix,
+ const char *nan_number, const char *pos_inf_number,
+ const char *neg_inf_number = "");
+
+private:
+ std::string Value(double v, const std::string &src) const FLATBUFFERS_OVERRIDE;
+ std::string Inf(double v) const FLATBUFFERS_OVERRIDE;
+
+ std::string NaN(double v) const FLATBUFFERS_OVERRIDE;
+
+ std::string Value(float v, const std::string &src) const FLATBUFFERS_OVERRIDE;
+ std::string Inf(float v) const FLATBUFFERS_OVERRIDE;
+ std::string NaN(float v) const FLATBUFFERS_OVERRIDE;
+
+ std::string MakeNaN(const std::string &prefix) const;
+ std::string MakeInf(bool neg, const std::string &prefix) const;
+
+ const std::string double_prefix_;
+ const std::string single_prefix_;
+ const std::string nan_number_;
+ const std::string pos_inf_number_;
+ const std::string neg_inf_number_;
+};
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_CODE_GENERATORS_H_
diff --git a/onert-micro/externals/flatbuffers/flatbuffers.h b/onert-micro/externals/flatbuffers/flatbuffers.h
new file mode 100644
index 000000000..3005d8921
--- /dev/null
+++ b/onert-micro/externals/flatbuffers/flatbuffers.h
@@ -0,0 +1,3078 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2014 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLATBUFFERS_H_
+#define FLATBUFFERS_H_
+
+#include "flatbuffers/base.h"
+#include "flatbuffers/stl_emulation.h"
+
+#ifndef FLATBUFFERS_CPP98_STL
+#include <functional>
+#endif
+
+#if defined(FLATBUFFERS_NAN_DEFAULTS)
+#include <cmath>
+#endif
+
+namespace flatbuffers
+{
+// Generic 'operator==' with conditional specialisations.
+// T e - new value of a scalar field.
+// T def - default of scalar (is known at compile-time).
+template <typename T> inline bool IsTheSameAs(T e, T def) { return e == def; }
+
+#if defined(FLATBUFFERS_NAN_DEFAULTS) && defined(FLATBUFFERS_HAS_NEW_STRTOD) && \
+ (FLATBUFFERS_HAS_NEW_STRTOD > 0)
+// Like `operator==(e, def)` with weak NaN if T=(float|double).
+template <typename T> inline bool IsFloatTheSameAs(T e, T def)
+{
+ return (e == def) || ((def != def) && (e != e));
+}
+template <> inline bool IsTheSameAs<float>(float e, float def) { return IsFloatTheSameAs(e, def); }
+template <> inline bool IsTheSameAs<double>(double e, double def)
+{
+ return IsFloatTheSameAs(e, def);
+}
+#endif
+
+// Check 'v' is out of closed range [low; high].
+// Workaround for GCC warning [-Werror=type-limits]:
+// comparison is always true due to limited range of data type.
+template <typename T> inline bool IsOutRange(const T &v, const T &low, const T &high)
+{
+ return (v < low) || (high < v);
+}
+
+// Check 'v' is in closed range [low; high].
+template <typename T> inline bool IsInRange(const T &v, const T &low, const T &high)
+{
+ return !IsOutRange(v, low, high);
+}
+
+// Wrapper for uoffset_t to allow safe template specialization.
+// Value is allowed to be 0 to indicate a null object (see e.g. AddOffset).
+template <typename T> struct Offset
+{
+ uoffset_t o;
+ Offset() : o(0) {}
+ Offset(uoffset_t _o) : o(_o) {}
+ Offset<void> Union() const { return Offset<void>(o); }
+ bool IsNull() const { return !o; }
+};
+
+inline void EndianCheck()
+{
+ int endiantest = 1;
+ // If this fails, see FLATBUFFERS_LITTLEENDIAN above.
+ FLATBUFFERS_ASSERT(*reinterpret_cast<char *>(&endiantest) == FLATBUFFERS_LITTLEENDIAN);
+ (void)endiantest;
+}
+
+template <typename T> FLATBUFFERS_CONSTEXPR size_t AlignOf()
+{
+#ifdef _MSC_VER
+ return __alignof(T);
+#else
+#ifndef alignof
+ return __alignof__(T);
+#else
+ return alignof(T);
+#endif
+#endif
+ // clang-format on
+}
+
+// When we read serialized data from memory, in the case of most scalars,
+// we want to just read T, but in the case of Offset, we want to actually
+// perform the indirection and return a pointer.
+// The template specialization below does just that.
+// It is wrapped in a struct since function templates can't overload on the
+// return type like this.
+// The typedef is for the convenience of callers of this function
+// (avoiding the need for a trailing return decltype)
+template <typename T> struct IndirectHelper
+{
+ typedef T return_type;
+ typedef T mutable_return_type;
+ static const size_t element_stride = sizeof(T);
+ static return_type Read(const uint8_t *p, uoffset_t i)
+ {
+ return EndianScalar((reinterpret_cast<const T *>(p))[i]);
+ }
+};
+template <typename T> struct IndirectHelper<Offset<T>>
+{
+ typedef const T *return_type;
+ typedef T *mutable_return_type;
+ static const size_t element_stride = sizeof(uoffset_t);
+ static return_type Read(const uint8_t *p, uoffset_t i)
+ {
+ p += i * sizeof(uoffset_t);
+ return reinterpret_cast<return_type>(p + ReadScalar<uoffset_t>(p));
+ }
+};
+template <typename T> struct IndirectHelper<const T *>
+{
+ typedef const T *return_type;
+ typedef T *mutable_return_type;
+ static const size_t element_stride = sizeof(T);
+ static return_type Read(const uint8_t *p, uoffset_t i)
+ {
+ return reinterpret_cast<const T *>(p + i * sizeof(T));
+ }
+};
+
+// An STL compatible iterator implementation for Vector below, effectively
+// calling Get() for every element.
+template <typename T, typename IT> struct VectorIterator
+{
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef IT value_type;
+ typedef ptrdiff_t difference_type;
+ typedef IT *pointer;
+ typedef IT &reference;
+
+ VectorIterator(const uint8_t *data, uoffset_t i)
+ : data_(data + IndirectHelper<T>::element_stride * i)
+ {
+ }
+ VectorIterator(const VectorIterator &other) : data_(other.data_) {}
+ VectorIterator() : data_(nullptr) {}
+
+ VectorIterator &operator=(const VectorIterator &other)
+ {
+ data_ = other.data_;
+ return *this;
+ }
+
+#if !defined(FLATBUFFERS_CPP98_STL)
+ VectorIterator &operator=(VectorIterator &&other)
+ {
+ data_ = other.data_;
+ return *this;
+ }
+#endif // !defined(FLATBUFFERS_CPP98_STL)
+ // clang-format on
+
+ bool operator==(const VectorIterator &other) const { return data_ == other.data_; }
+
+ bool operator<(const VectorIterator &other) const { return data_ < other.data_; }
+
+ bool operator!=(const VectorIterator &other) const { return data_ != other.data_; }
+
+ difference_type operator-(const VectorIterator &other) const
+ {
+ return (data_ - other.data_) / IndirectHelper<T>::element_stride;
+ }
+
+ // Note: return type is incompatible with the standard
+ // `reference operator*()`.
+ IT operator*() const { return IndirectHelper<T>::Read(data_, 0); }
+
+ // Note: return type is incompatible with the standard
+ // `pointer operator->()`.
+ IT operator->() const { return IndirectHelper<T>::Read(data_, 0); }
+
+ VectorIterator &operator++()
+ {
+ data_ += IndirectHelper<T>::element_stride;
+ return *this;
+ }
+
+ VectorIterator operator++(int)
+ {
+ VectorIterator temp(data_, 0);
+ data_ += IndirectHelper<T>::element_stride;
+ return temp;
+ }
+
+ VectorIterator operator+(const uoffset_t &offset) const
+ {
+ return VectorIterator(data_ + offset * IndirectHelper<T>::element_stride, 0);
+ }
+
+ VectorIterator &operator+=(const uoffset_t &offset)
+ {
+ data_ += offset * IndirectHelper<T>::element_stride;
+ return *this;
+ }
+
+ VectorIterator &operator--()
+ {
+ data_ -= IndirectHelper<T>::element_stride;
+ return *this;
+ }
+
+ VectorIterator operator--(int)
+ {
+ VectorIterator temp(data_, 0);
+ data_ -= IndirectHelper<T>::element_stride;
+ return temp;
+ }
+
+ VectorIterator operator-(const uoffset_t &offset) const
+ {
+ return VectorIterator(data_ - offset * IndirectHelper<T>::element_stride, 0);
+ }
+
+ VectorIterator &operator-=(const uoffset_t &offset)
+ {
+ data_ -= offset * IndirectHelper<T>::element_stride;
+ return *this;
+ }
+
+private:
+ const uint8_t *data_;
+};
+
+template <typename Iterator> struct VectorReverseIterator : public std::reverse_iterator<Iterator>
+{
+ explicit VectorReverseIterator(Iterator iter) : std::reverse_iterator<Iterator>(iter) {}
+
+ // Note: return type is incompatible with the standard
+ // `reference operator*()`.
+ typename Iterator::value_type operator*() const
+ {
+ auto tmp = std::reverse_iterator<Iterator>::current;
+ return *--tmp;
+ }
+
+ // Note: return type is incompatible with the standard
+ // `pointer operator->()`.
+ typename Iterator::value_type operator->() const
+ {
+ auto tmp = std::reverse_iterator<Iterator>::current;
+ return *--tmp;
+ }
+};
+
+struct String;
+
+// This is used as a helper type for accessing vectors.
+// Vector::data() assumes the vector elements start after the length field.
+template <typename T> class Vector
+{
+public:
+ typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type> iterator;
+ typedef VectorIterator<T, typename IndirectHelper<T>::return_type> const_iterator;
+ typedef VectorReverseIterator<iterator> reverse_iterator;
+ typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
+
+ uoffset_t size() const { return EndianScalar(length_); }
+
+ // Deprecated: use size(). Here for backwards compatibility.
+ FLATBUFFERS_ATTRIBUTE(deprecated("use size() instead"))
+ uoffset_t Length() const { return size(); }
+
+ typedef typename IndirectHelper<T>::return_type return_type;
+ typedef typename IndirectHelper<T>::mutable_return_type mutable_return_type;
+ typedef return_type value_type;
+
+ return_type Get(uoffset_t i) const
+ {
+ FLATBUFFERS_ASSERT(i < size());
+ return IndirectHelper<T>::Read(Data(), i);
+ }
+
+ return_type operator[](uoffset_t i) const { return Get(i); }
+
+ // If this is a Vector of enums, T will be its storage type, not the enum
+ // type. This function makes it convenient to retrieve value with enum
+ // type E.
+ template <typename E> E GetEnum(uoffset_t i) const { return static_cast<E>(Get(i)); }
+
+ // If this a vector of unions, this does the cast for you. There's no check
+ // to make sure this is the right type!
+ template <typename U> const U *GetAs(uoffset_t i) const
+ {
+ return reinterpret_cast<const U *>(Get(i));
+ }
+
+ // If this a vector of unions, this does the cast for you. There's no check
+ // to make sure this is actually a string!
+ const String *GetAsString(uoffset_t i) const { return reinterpret_cast<const String *>(Get(i)); }
+
+ const void *GetStructFromOffset(size_t o) const
+ {
+ return reinterpret_cast<const void *>(Data() + o);
+ }
+
+ iterator begin() { return iterator(Data(), 0); }
+ const_iterator begin() const { return const_iterator(Data(), 0); }
+
+ iterator end() { return iterator(Data(), size()); }
+ const_iterator end() const { return const_iterator(Data(), size()); }
+
+ reverse_iterator rbegin() { return reverse_iterator(end()); }
+ const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
+
+ reverse_iterator rend() { return reverse_iterator(begin()); }
+ const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
+
+ const_iterator cbegin() const { return begin(); }
+
+ const_iterator cend() const { return end(); }
+
+ const_reverse_iterator crbegin() const { return rbegin(); }
+
+ const_reverse_iterator crend() const { return rend(); }
+
+ // Change elements if you have a non-const pointer to this object.
+ // Scalars only. See reflection.h, and the documentation.
+ void Mutate(uoffset_t i, const T &val)
+ {
+ FLATBUFFERS_ASSERT(i < size());
+ WriteScalar(data() + i, val);
+ }
+
+ // Change an element of a vector of tables (or strings).
+ // "val" points to the new table/string, as you can obtain from
+ // e.g. reflection::AddFlatBuffer().
+ void MutateOffset(uoffset_t i, const uint8_t *val)
+ {
+ FLATBUFFERS_ASSERT(i < size());
+ static_assert(sizeof(T) == sizeof(uoffset_t), "Unrelated types");
+ WriteScalar(data() + i, static_cast<uoffset_t>(val - (Data() + i * sizeof(uoffset_t))));
+ }
+
+ // Get a mutable pointer to tables/strings inside this vector.
+ mutable_return_type GetMutableObject(uoffset_t i) const
+ {
+ FLATBUFFERS_ASSERT(i < size());
+ return const_cast<mutable_return_type>(IndirectHelper<T>::Read(Data(), i));
+ }
+
+ // The raw data in little endian format. Use with care.
+ const uint8_t *Data() const { return reinterpret_cast<const uint8_t *>(&length_ + 1); }
+
+ uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
+
+ // Similarly, but typed, much like std::vector::data
+ const T *data() const { return reinterpret_cast<const T *>(Data()); }
+ T *data() { return reinterpret_cast<T *>(Data()); }
+
+ template <typename K> return_type LookupByKey(K key) const
+ {
+ void *search_result =
+ std::bsearch(&key, Data(), size(), IndirectHelper<T>::element_stride, KeyCompare<K>);
+
+ if (!search_result)
+ {
+ return nullptr; // Key not found.
+ }
+
+ const uint8_t *element = reinterpret_cast<const uint8_t *>(search_result);
+
+ return IndirectHelper<T>::Read(element, 0);
+ }
+
+protected:
+ // This class is only used to access pre-existing data. Don't ever
+ // try to construct these manually.
+ Vector();
+
+ uoffset_t length_;
+
+private:
+ // This class is a pointer. Copying will therefore create an invalid object.
+ // Private and unimplemented copy constructor.
+ Vector(const Vector &);
+ Vector &operator=(const Vector &);
+
+ template <typename K> static int KeyCompare(const void *ap, const void *bp)
+ {
+ const K *key = reinterpret_cast<const K *>(ap);
+ const uint8_t *data = reinterpret_cast<const uint8_t *>(bp);
+ auto table = IndirectHelper<T>::Read(data, 0);
+
+ // std::bsearch compares with the operands transposed, so we negate the
+ // result here.
+ return -table->KeyCompareWithValue(*key);
+ }
+};
+
+// Represent a vector much like the template above, but in this case we
+// don't know what the element types are (used with reflection.h).
+class VectorOfAny
+{
+public:
+ uoffset_t size() const { return EndianScalar(length_); }
+
+ const uint8_t *Data() const { return reinterpret_cast<const uint8_t *>(&length_ + 1); }
+ uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
+
+protected:
+ VectorOfAny();
+
+ uoffset_t length_;
+
+private:
+ VectorOfAny(const VectorOfAny &);
+ VectorOfAny &operator=(const VectorOfAny &);
+};
+
+#ifndef FLATBUFFERS_CPP98_STL
+template <typename T, typename U> Vector<Offset<T>> *VectorCast(Vector<Offset<U>> *ptr)
+{
+ static_assert(std::is_base_of<T, U>::value, "Unrelated types");
+ return reinterpret_cast<Vector<Offset<T>> *>(ptr);
+}
+
+template <typename T, typename U> const Vector<Offset<T>> *VectorCast(const Vector<Offset<U>> *ptr)
+{
+ static_assert(std::is_base_of<T, U>::value, "Unrelated types");
+ return reinterpret_cast<const Vector<Offset<T>> *>(ptr);
+}
+#endif
+
+// Convenient helper function to get the length of any vector, regardless
+// of whether it is null or not (the field is not set).
+template <typename T> static inline size_t VectorLength(const Vector<T> *v)
+{
+ return v ? v->size() : 0;
+}
+
+// This is used as a helper type for accessing arrays.
+template <typename T, uint16_t length> class Array
+{
+ typedef typename flatbuffers::integral_constant<bool, flatbuffers::is_scalar<T>::value>
+ scalar_tag;
+ typedef
+ typename flatbuffers::conditional<scalar_tag::value, T, const T *>::type IndirectHelperType;
+
+public:
+ typedef uint16_t size_type;
+ typedef typename IndirectHelper<IndirectHelperType>::return_type return_type;
+ typedef VectorIterator<T, return_type> const_iterator;
+ typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
+
+ FLATBUFFERS_CONSTEXPR uint16_t size() const { return length; }
+
+ return_type Get(uoffset_t i) const
+ {
+ FLATBUFFERS_ASSERT(i < size());
+ return IndirectHelper<IndirectHelperType>::Read(Data(), i);
+ }
+
+ return_type operator[](uoffset_t i) const { return Get(i); }
+
+ // If this is a Vector of enums, T will be its storage type, not the enum
+ // type. This function makes it convenient to retrieve value with enum
+ // type E.
+ template <typename E> E GetEnum(uoffset_t i) const { return static_cast<E>(Get(i)); }
+
+ const_iterator begin() const { return const_iterator(Data(), 0); }
+ const_iterator end() const { return const_iterator(Data(), size()); }
+
+ const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
+ const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
+
+ const_iterator cbegin() const { return begin(); }
+ const_iterator cend() const { return end(); }
+
+ const_reverse_iterator crbegin() const { return rbegin(); }
+ const_reverse_iterator crend() const { return rend(); }
+
+ // Get a mutable pointer to elements inside this array.
+ // This method used to mutate arrays of structs followed by a @p Mutate
+ // operation. For primitive types use @p Mutate directly.
+ // @warning Assignments and reads to/from the dereferenced pointer are not
+ // automatically converted to the correct endianness.
+ typename flatbuffers::conditional<scalar_tag::value, void, T *>::type
+ GetMutablePointer(uoffset_t i) const
+ {
+ FLATBUFFERS_ASSERT(i < size());
+ return const_cast<T *>(&data()[i]);
+ }
+
+ // Change elements if you have a non-const pointer to this object.
+ void Mutate(uoffset_t i, const T &val) { MutateImpl(scalar_tag(), i, val); }
+
+ // The raw data in little endian format. Use with care.
+ const uint8_t *Data() const { return data_; }
+
+ uint8_t *Data() { return data_; }
+
+ // Similarly, but typed, much like std::vector::data
+ const T *data() const { return reinterpret_cast<const T *>(Data()); }
+ T *data() { return reinterpret_cast<T *>(Data()); }
+
+ // Copy data from a span with endian conversion.
+ // If this Array and the span overlap, the behavior is undefined.
+ void CopyFromSpan(flatbuffers::span<const T, length> src)
+ {
+ const auto p1 = reinterpret_cast<const uint8_t *>(src.data());
+ const auto p2 = Data();
+ FLATBUFFERS_ASSERT(!(p1 >= p2 && p1 < (p2 + length)) && !(p2 >= p1 && p2 < (p1 + length)));
+ (void)p1;
+ (void)p2;
+
+ CopyFromSpanImpl(flatbuffers::integral_constant < bool,
+ !scalar_tag::value || sizeof(T) == 1 || FLATBUFFERS_LITTLEENDIAN > (), src);
+ }
+
+protected:
+ void MutateImpl(flatbuffers::integral_constant<bool, true>, uoffset_t i, const T &val)
+ {
+ FLATBUFFERS_ASSERT(i < size());
+ WriteScalar(data() + i, val);
+ }
+
+ void MutateImpl(flatbuffers::integral_constant<bool, false>, uoffset_t i, const T &val)
+ {
+ *(GetMutablePointer(i)) = val;
+ }
+
+ void CopyFromSpanImpl(flatbuffers::integral_constant<bool, true>,
+ flatbuffers::span<const T, length> src)
+ {
+ // Use std::memcpy() instead of std::copy() to avoid preformance degradation
+ // due to aliasing if T is char or unsigned char.
+ // The size is known at compile time, so memcpy would be inlined.
+ std::memcpy(data(), src.data(), length * sizeof(T));
+ }
+
+ // Copy data from flatbuffers::span with endian conversion.
+ void CopyFromSpanImpl(flatbuffers::integral_constant<bool, false>,
+ flatbuffers::span<const T, length> src)
+ {
+ for (size_type k = 0; k < length; k++)
+ {
+ Mutate(k, src[k]);
+ }
+ }
+
+ // This class is only used to access pre-existing data. Don't ever
+ // try to construct these manually.
+ // 'constexpr' allows us to use 'size()' at compile time.
+ // @note Must not use 'FLATBUFFERS_CONSTEXPR' here, as const is not allowed on
+ // a constructor.
+#if defined(__cpp_constexpr)
+ constexpr Array();
+#else
+ Array();
+#endif
+
+ uint8_t data_[length * sizeof(T)];
+
+private:
+ // This class is a pointer. Copying will therefore create an invalid object.
+ // Private and unimplemented copy constructor.
+ Array(const Array &);
+ Array &operator=(const Array &);
+};
+
+// Specialization for Array[struct] with access using Offset<void> pointer.
+// This specialization used by idl_gen_text.cpp.
+template <typename T, uint16_t length> class Array<Offset<T>, length>
+{
+ static_assert(flatbuffers::is_same<T, void>::value, "unexpected type T");
+
+public:
+ typedef const void *return_type;
+
+ const uint8_t *Data() const { return data_; }
+
+ // Make idl_gen_text.cpp::PrintContainer happy.
+ return_type operator[](uoffset_t) const
+ {
+ FLATBUFFERS_ASSERT(false);
+ return nullptr;
+ }
+
+private:
+ // This class is only used to access pre-existing data.
+ Array();
+ Array(const Array &);
+ Array &operator=(const Array &);
+
+ uint8_t data_[1];
+};
+
+// Cast a raw T[length] to a raw flatbuffers::Array<T, length>
+// without endian conversion. Use with care.
+template <typename T, uint16_t length> Array<T, length> &CastToArray(T (&arr)[length])
+{
+ return *reinterpret_cast<Array<T, length> *>(arr);
+}
+
+template <typename T, uint16_t length> const Array<T, length> &CastToArray(const T (&arr)[length])
+{
+ return *reinterpret_cast<const Array<T, length> *>(arr);
+}
+
+template <typename E, typename T, uint16_t length>
+Array<E, length> &CastToArrayOfEnum(T (&arr)[length])
+{
+ static_assert(sizeof(E) == sizeof(T), "invalid enum type E");
+ return *reinterpret_cast<Array<E, length> *>(arr);
+}
+
+template <typename E, typename T, uint16_t length>
+const Array<E, length> &CastToArrayOfEnum(const T (&arr)[length])
+{
+ static_assert(sizeof(E) == sizeof(T), "invalid enum type E");
+ return *reinterpret_cast<const Array<E, length> *>(arr);
+}
+
+// Lexicographically compare two strings (possibly containing nulls), and
+// return true if the first is less than the second.
+static inline bool StringLessThan(const char *a_data, uoffset_t a_size, const char *b_data,
+ uoffset_t b_size)
+{
+ const auto cmp = memcmp(a_data, b_data, (std::min)(a_size, b_size));
+ return cmp == 0 ? a_size < b_size : cmp < 0;
+}
+
+struct String : public Vector<char>
+{
+ const char *c_str() const { return reinterpret_cast<const char *>(Data()); }
+ std::string str() const { return std::string(c_str(), size()); }
+
+#ifdef FLATBUFFERS_HAS_STRING_VIEW
+ flatbuffers::string_view string_view() const { return flatbuffers::string_view(c_str(), size()); }
+#endif // FLATBUFFERS_HAS_STRING_VIEW
+ // clang-format on
+
+ bool operator<(const String &o) const
+ {
+ return StringLessThan(this->data(), this->size(), o.data(), o.size());
+ }
+};
+
+// Convenience function to get std::string from a String returning an empty
+// string on null pointer.
+static inline std::string GetString(const String *str) { return str ? str->str() : ""; }
+
+// Convenience function to get char* from a String returning an empty string on
+// null pointer.
+static inline const char *GetCstring(const String *str) { return str ? str->c_str() : ""; }
+
+#ifdef FLATBUFFERS_HAS_STRING_VIEW
+// Convenience function to get string_view from a String returning an empty
+// string_view on null pointer.
+static inline flatbuffers::string_view GetStringView(const String *str)
+{
+ return str ? str->string_view() : flatbuffers::string_view();
+}
+#endif // FLATBUFFERS_HAS_STRING_VIEW
+
+// Allocator interface. This is flatbuffers-specific and meant only for
+// `vector_downward` usage.
+class Allocator
+{
+public:
+ virtual ~Allocator() {}
+
+ // Allocate `size` bytes of memory.
+ virtual uint8_t *allocate(size_t size) = 0;
+
+ // Deallocate `size` bytes of memory at `p` allocated by this allocator.
+ virtual void deallocate(uint8_t *p, size_t size) = 0;
+
+ // Reallocate `new_size` bytes of memory, replacing the old region of size
+ // `old_size` at `p`. In contrast to a normal realloc, this grows downwards,
+ // and is intended specifcally for `vector_downward` use.
+ // `in_use_back` and `in_use_front` indicate how much of `old_size` is
+ // actually in use at each end, and needs to be copied.
+ virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size, size_t new_size,
+ size_t in_use_back, size_t in_use_front)
+ {
+ FLATBUFFERS_ASSERT(new_size > old_size); // vector_downward only grows
+ uint8_t *new_p = allocate(new_size);
+ memcpy_downward(old_p, old_size, new_p, new_size, in_use_back, in_use_front);
+ deallocate(old_p, old_size);
+ return new_p;
+ }
+
+protected:
+ // Called by `reallocate_downward` to copy memory from `old_p` of `old_size`
+ // to `new_p` of `new_size`. Only memory of size `in_use_front` and
+ // `in_use_back` will be copied from the front and back of the old memory
+ // allocation.
+ void memcpy_downward(uint8_t *old_p, size_t old_size, uint8_t *new_p, size_t new_size,
+ size_t in_use_back, size_t in_use_front)
+ {
+ memcpy(new_p + new_size - in_use_back, old_p + old_size - in_use_back, in_use_back);
+ memcpy(new_p, old_p, in_use_front);
+ }
+};
+
+// DefaultAllocator uses new/delete to allocate memory regions
+class DefaultAllocator : public Allocator
+{
+public:
+ uint8_t *allocate(size_t size) FLATBUFFERS_OVERRIDE { return new uint8_t[size]; }
+
+ void deallocate(uint8_t *p, size_t) FLATBUFFERS_OVERRIDE { delete[] p; }
+
+ static void dealloc(void *p, size_t) { delete[] static_cast<uint8_t *>(p); }
+};
+
+// These functions allow for a null allocator to mean use the default allocator,
+// as used by DetachedBuffer and vector_downward below.
+// This is to avoid having a statically or dynamically allocated default
+// allocator, or having to move it between the classes that may own it.
+inline uint8_t *Allocate(Allocator *allocator, size_t size)
+{
+ return allocator ? allocator->allocate(size) : DefaultAllocator().allocate(size);
+}
+
+inline void Deallocate(Allocator *allocator, uint8_t *p, size_t size)
+{
+ if (allocator)
+ allocator->deallocate(p, size);
+ else
+ DefaultAllocator().deallocate(p, size);
+}
+
+inline uint8_t *ReallocateDownward(Allocator *allocator, uint8_t *old_p, size_t old_size,
+ size_t new_size, size_t in_use_back, size_t in_use_front)
+{
+ return allocator
+ ? allocator->reallocate_downward(old_p, old_size, new_size, in_use_back, in_use_front)
+ : DefaultAllocator().reallocate_downward(old_p, old_size, new_size, in_use_back,
+ in_use_front);
+}
+
+// DetachedBuffer is a finished flatbuffer memory region, detached from its
+// builder. The original memory region and allocator are also stored so that
+// the DetachedBuffer can manage the memory lifetime.
+class DetachedBuffer
+{
+public:
+ DetachedBuffer()
+ : allocator_(nullptr), own_allocator_(false), buf_(nullptr), reserved_(0), cur_(nullptr),
+ size_(0)
+ {
+ }
+
+ DetachedBuffer(Allocator *allocator, bool own_allocator, uint8_t *buf, size_t reserved,
+ uint8_t *cur, size_t sz)
+ : allocator_(allocator), own_allocator_(own_allocator), buf_(buf), reserved_(reserved),
+ cur_(cur), size_(sz)
+ {
+ }
+
+#if !defined(FLATBUFFERS_CPP98_STL)
+ // clang-format on
+ DetachedBuffer(DetachedBuffer &&other)
+ : allocator_(other.allocator_), own_allocator_(other.own_allocator_), buf_(other.buf_),
+ reserved_(other.reserved_), cur_(other.cur_), size_(other.size_)
+ {
+ other.reset();
+ }
+#endif // !defined(FLATBUFFERS_CPP98_STL)
+
+#if !defined(FLATBUFFERS_CPP98_STL)
+ // clang-format on
+ DetachedBuffer &operator=(DetachedBuffer &&other)
+ {
+ if (this == &other)
+ return *this;
+
+ destroy();
+
+ allocator_ = other.allocator_;
+ own_allocator_ = other.own_allocator_;
+ buf_ = other.buf_;
+ reserved_ = other.reserved_;
+ cur_ = other.cur_;
+ size_ = other.size_;
+
+ other.reset();
+
+ return *this;
+ }
+#endif // !defined(FLATBUFFERS_CPP98_STL)
+ // clang-format on
+
+ ~DetachedBuffer() { destroy(); }
+
+ const uint8_t *data() const { return cur_; }
+
+ uint8_t *data() { return cur_; }
+
+ size_t size() const { return size_; }
+
+#if 0 // disabled for now due to the ordering of classes in this header
+ template <class T>
+ bool Verify() const {
+ Verifier verifier(data(), size());
+ return verifier.Verify<T>(nullptr);
+ }
+
+ template <class T>
+ const T* GetRoot() const {
+ return flatbuffers::GetRoot<T>(data());
+ }
+
+ template <class T>
+ T* GetRoot() {
+ return flatbuffers::GetRoot<T>(data());
+ }
+#endif
+
+#if !defined(FLATBUFFERS_CPP98_STL)
+ // clang-format on
+ // These may change access mode, leave these at end of public section
+ FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer &other));
+ FLATBUFFERS_DELETE_FUNC(DetachedBuffer &operator=(const DetachedBuffer &other));
+#endif // !defined(FLATBUFFERS_CPP98_STL)
+ // clang-format on
+
+protected:
+ Allocator *allocator_;
+ bool own_allocator_;
+ uint8_t *buf_;
+ size_t reserved_;
+ uint8_t *cur_;
+ size_t size_;
+
+ inline void destroy()
+ {
+ if (buf_)
+ Deallocate(allocator_, buf_, reserved_);
+ if (own_allocator_ && allocator_)
+ {
+ delete allocator_;
+ }
+ reset();
+ }
+
+ inline void reset()
+ {
+ allocator_ = nullptr;
+ own_allocator_ = false;
+ buf_ = nullptr;
+ reserved_ = 0;
+ cur_ = nullptr;
+ size_ = 0;
+ }
+};
+
+// This is a minimal replication of std::vector<uint8_t> functionality,
+// except growing from higher to lower addresses. i.e push_back() inserts data
+// in the lowest address in the vector.
+// Since this vector leaves the lower part unused, we support a "scratch-pad"
+// that can be stored there for temporary data, to share the allocated space.
+// Essentially, this supports 2 std::vectors in a single buffer.
+class vector_downward
+{
+public:
+ explicit vector_downward(size_t initial_size, Allocator *allocator, bool own_allocator,
+ size_t buffer_minalign)
+ : allocator_(allocator), own_allocator_(own_allocator), initial_size_(initial_size),
+ buffer_minalign_(buffer_minalign), reserved_(0), buf_(nullptr), cur_(nullptr),
+ scratch_(nullptr)
+ {
+ }
+
+#if !defined(FLATBUFFERS_CPP98_STL)
+ vector_downward(vector_downward &&other)
+#else
+ vector_downward(vector_downward &other)
+#endif // defined(FLATBUFFERS_CPP98_STL)
+ // clang-format on
+ : allocator_(other.allocator_), own_allocator_(other.own_allocator_),
+ initial_size_(other.initial_size_), buffer_minalign_(other.buffer_minalign_),
+ reserved_(other.reserved_), buf_(other.buf_), cur_(other.cur_), scratch_(other.scratch_)
+ {
+ // No change in other.allocator_
+ // No change in other.initial_size_
+ // No change in other.buffer_minalign_
+ other.own_allocator_ = false;
+ other.reserved_ = 0;
+ other.buf_ = nullptr;
+ other.cur_ = nullptr;
+ other.scratch_ = nullptr;
+ }
+
+#if !defined(FLATBUFFERS_CPP98_STL)
+ // clang-format on
+ vector_downward &operator=(vector_downward &&other)
+ {
+ // Move construct a temporary and swap idiom
+ vector_downward temp(std::move(other));
+ swap(temp);
+ return *this;
+ }
+#endif // defined(FLATBUFFERS_CPP98_STL)
+ // clang-format on
+
+ ~vector_downward()
+ {
+ clear_buffer();
+ clear_allocator();
+ }
+
+ void reset()
+ {
+ clear_buffer();
+ clear();
+ }
+
+ void clear()
+ {
+ if (buf_)
+ {
+ cur_ = buf_ + reserved_;
+ }
+ else
+ {
+ reserved_ = 0;
+ cur_ = nullptr;
+ }
+ clear_scratch();
+ }
+
+ void clear_scratch() { scratch_ = buf_; }
+
+ void clear_allocator()
+ {
+ if (own_allocator_ && allocator_)
+ {
+ delete allocator_;
+ }
+ allocator_ = nullptr;
+ own_allocator_ = false;
+ }
+
+ void clear_buffer()
+ {
+ if (buf_)
+ Deallocate(allocator_, buf_, reserved_);
+ buf_ = nullptr;
+ }
+
+ // Relinquish the pointer to the caller.
+ uint8_t *release_raw(size_t &allocated_bytes, size_t &offset)
+ {
+ auto *buf = buf_;
+ allocated_bytes = reserved_;
+ offset = static_cast<size_t>(cur_ - buf_);
+
+ // release_raw only relinquishes the buffer ownership.
+ // Does not deallocate or reset the allocator. Destructor will do that.
+ buf_ = nullptr;
+ clear();
+ return buf;
+ }
+
+ // Relinquish the pointer to the caller.
+ DetachedBuffer release()
+ {
+ // allocator ownership (if any) is transferred to DetachedBuffer.
+ DetachedBuffer fb(allocator_, own_allocator_, buf_, reserved_, cur_, size());
+ if (own_allocator_)
+ {
+ allocator_ = nullptr;
+ own_allocator_ = false;
+ }
+ buf_ = nullptr;
+ clear();
+ return fb;
+ }
+
+ size_t ensure_space(size_t len)
+ {
+ FLATBUFFERS_ASSERT(cur_ >= scratch_ && scratch_ >= buf_);
+ if (len > static_cast<size_t>(cur_ - scratch_))
+ {
+ reallocate(len);
+ }
+ // Beyond this, signed offsets may not have enough range:
+ // (FlatBuffers > 2GB not supported).
+ FLATBUFFERS_ASSERT(size() < FLATBUFFERS_MAX_BUFFER_SIZE);
+ return len;
+ }
+
+ inline uint8_t *make_space(size_t len)
+ {
+ size_t space = ensure_space(len);
+ cur_ -= space;
+ return cur_;
+ }
+
+ // Returns nullptr if using the DefaultAllocator.
+ Allocator *get_custom_allocator() { return allocator_; }
+
+ uoffset_t size() const
+ {
+ return static_cast<uoffset_t>(reserved_ - static_cast<size_t>(cur_ - buf_));
+ }
+
+ uoffset_t scratch_size() const { return static_cast<uoffset_t>(scratch_ - buf_); }
+
+ size_t capacity() const { return reserved_; }
+
+ uint8_t *data() const
+ {
+ FLATBUFFERS_ASSERT(cur_);
+ return cur_;
+ }
+
+ uint8_t *scratch_data() const
+ {
+ FLATBUFFERS_ASSERT(buf_);
+ return buf_;
+ }
+
+ uint8_t *scratch_end() const
+ {
+ FLATBUFFERS_ASSERT(scratch_);
+ return scratch_;
+ }
+
+ uint8_t *data_at(size_t offset) const { return buf_ + reserved_ - offset; }
+
+ void push(const uint8_t *bytes, size_t num)
+ {
+ if (num > 0)
+ {
+ memcpy(make_space(num), bytes, num);
+ }
+ }
+
+ // Specialized version of push() that avoids memcpy call for small data.
+ template <typename T> void push_small(const T &little_endian_t)
+ {
+ make_space(sizeof(T));
+ *reinterpret_cast<T *>(cur_) = little_endian_t;
+ }
+
+ template <typename T> void scratch_push_small(const T &t)
+ {
+ ensure_space(sizeof(T));
+ *reinterpret_cast<T *>(scratch_) = t;
+ scratch_ += sizeof(T);
+ }
+
+ // fill() is most frequently called with small byte counts (<= 4),
+ // which is why we're using loops rather than calling memset.
+ void fill(size_t zero_pad_bytes)
+ {
+ make_space(zero_pad_bytes);
+ for (size_t i = 0; i < zero_pad_bytes; i++)
+ cur_[i] = 0;
+ }
+
+ // Version for when we know the size is larger.
+ // Precondition: zero_pad_bytes > 0
+ void fill_big(size_t zero_pad_bytes) { memset(make_space(zero_pad_bytes), 0, zero_pad_bytes); }
+
+ void pop(size_t bytes_to_remove) { cur_ += bytes_to_remove; }
+ void scratch_pop(size_t bytes_to_remove) { scratch_ -= bytes_to_remove; }
+
+ void swap(vector_downward &other)
+ {
+ using std::swap;
+ swap(allocator_, other.allocator_);
+ swap(own_allocator_, other.own_allocator_);
+ swap(initial_size_, other.initial_size_);
+ swap(buffer_minalign_, other.buffer_minalign_);
+ swap(reserved_, other.reserved_);
+ swap(buf_, other.buf_);
+ swap(cur_, other.cur_);
+ swap(scratch_, other.scratch_);
+ }
+
+ void swap_allocator(vector_downward &other)
+ {
+ using std::swap;
+ swap(allocator_, other.allocator_);
+ swap(own_allocator_, other.own_allocator_);
+ }
+
+private:
+ // You shouldn't really be copying instances of this class.
+ FLATBUFFERS_DELETE_FUNC(vector_downward(const vector_downward &));
+ FLATBUFFERS_DELETE_FUNC(vector_downward &operator=(const vector_downward &));
+
+ Allocator *allocator_;
+ bool own_allocator_;
+ size_t initial_size_;
+ size_t buffer_minalign_;
+ size_t reserved_;
+ uint8_t *buf_;
+ uint8_t *cur_; // Points at location between empty (below) and used (above).
+ uint8_t *scratch_; // Points to the end of the scratchpad in use.
+
+ void reallocate(size_t len)
+ {
+ auto old_reserved = reserved_;
+ auto old_size = size();
+ auto old_scratch_size = scratch_size();
+ reserved_ += (std::max)(len, old_reserved ? old_reserved / 2 : initial_size_);
+ reserved_ = (reserved_ + buffer_minalign_ - 1) & ~(buffer_minalign_ - 1);
+ if (buf_)
+ {
+ buf_ =
+ ReallocateDownward(allocator_, buf_, old_reserved, reserved_, old_size, old_scratch_size);
+ }
+ else
+ {
+ buf_ = Allocate(allocator_, reserved_);
+ }
+ cur_ = buf_ + reserved_ - old_size;
+ scratch_ = buf_ + old_scratch_size;
+ }
+};
+
+// Converts a Field ID to a virtual table offset.
+inline voffset_t FieldIndexToOffset(voffset_t field_id)
+{
+ // Should correspond to what EndTable() below builds up.
+ const int fixed_fields = 2; // Vtable size and Object Size.
+ return static_cast<voffset_t>((field_id + fixed_fields) * sizeof(voffset_t));
+}
+
+template <typename T, typename Alloc> const T *data(const std::vector<T, Alloc> &v)
+{
+ // Eventually the returned pointer gets passed down to memcpy, so
+ // we need it to be non-null to avoid undefined behavior.
+ static uint8_t t;
+ return v.empty() ? reinterpret_cast<const T *>(&t) : &v.front();
+}
+template <typename T, typename Alloc> T *data(std::vector<T, Alloc> &v)
+{
+ // Eventually the returned pointer gets passed down to memcpy, so
+ // we need it to be non-null to avoid undefined behavior.
+ static uint8_t t;
+ return v.empty() ? reinterpret_cast<T *>(&t) : &v.front();
+}
+
+/// @endcond
+
+/// @addtogroup flatbuffers_cpp_api
+/// @{
+/// @class FlatBufferBuilder
+/// @brief Helper class to hold data needed in creation of a FlatBuffer.
+/// To serialize data, you typically call one of the `Create*()` functions in
+/// the generated code, which in turn call a sequence of `StartTable`/
+/// `PushElement`/`AddElement`/`EndTable`, or the builtin `CreateString`/
+/// `CreateVector` functions. Do this is depth-first order to build up a tree to
+/// the root. `Finish()` wraps up the buffer ready for transport.
+class FlatBufferBuilder
+{
+public:
+ /// @brief Default constructor for FlatBufferBuilder.
+ /// @param[in] initial_size The initial size of the buffer, in bytes. Defaults
+ /// to `1024`.
+ /// @param[in] allocator An `Allocator` to use. If null will use
+ /// `DefaultAllocator`.
+ /// @param[in] own_allocator Whether the builder/vector should own the
+ /// allocator. Defaults to / `false`.
+ /// @param[in] buffer_minalign Force the buffer to be aligned to the given
+ /// minimum alignment upon reallocation. Only needed if you intend to store
+ /// types with custom alignment AND you wish to read the buffer in-place
+ /// directly after creation.
+ explicit FlatBufferBuilder(size_t initial_size = 1024, Allocator *allocator = nullptr,
+ bool own_allocator = false,
+ size_t buffer_minalign = AlignOf<largest_scalar_t>())
+ : buf_(initial_size, allocator, own_allocator, buffer_minalign), num_field_loc(0),
+ max_voffset_(0), nested(false), finished(false), minalign_(1), force_defaults_(false),
+ dedup_vtables_(true), string_pool(nullptr)
+ {
+ EndianCheck();
+ }
+
+/// @brief Move constructor for FlatBufferBuilder.
+#if !defined(FLATBUFFERS_CPP98_STL)
+ FlatBufferBuilder(FlatBufferBuilder &&other)
+#else
+ FlatBufferBuilder(FlatBufferBuilder &other)
+#endif // #if !defined(FLATBUFFERS_CPP98_STL)
+ : buf_(1024, nullptr, false, AlignOf<largest_scalar_t>()), num_field_loc(0), max_voffset_(0),
+ nested(false), finished(false), minalign_(1), force_defaults_(false), dedup_vtables_(true),
+ string_pool(nullptr)
+ {
+ EndianCheck();
+ // Default construct and swap idiom.
+ // Lack of delegating constructors in vs2010 makes it more verbose than needed.
+ Swap(other);
+ }
+
+#if !defined(FLATBUFFERS_CPP98_STL)
+ // clang-format on
+ /// @brief Move assignment operator for FlatBufferBuilder.
+ FlatBufferBuilder &operator=(FlatBufferBuilder &&other)
+ {
+ // Move construct a temporary and swap idiom
+ FlatBufferBuilder temp(std::move(other));
+ Swap(temp);
+ return *this;
+ }
+#endif // defined(FLATBUFFERS_CPP98_STL)
+ // clang-format on
+
+ void Swap(FlatBufferBuilder &other)
+ {
+ using std::swap;
+ buf_.swap(other.buf_);
+ swap(num_field_loc, other.num_field_loc);
+ swap(max_voffset_, other.max_voffset_);
+ swap(nested, other.nested);
+ swap(finished, other.finished);
+ swap(minalign_, other.minalign_);
+ swap(force_defaults_, other.force_defaults_);
+ swap(dedup_vtables_, other.dedup_vtables_);
+ swap(string_pool, other.string_pool);
+ }
+
+ ~FlatBufferBuilder()
+ {
+ if (string_pool)
+ delete string_pool;
+ }
+
+ void Reset()
+ {
+ Clear(); // clear builder state
+ buf_.reset(); // deallocate buffer
+ }
+
+ /// @brief Reset all the state in this FlatBufferBuilder so it can be reused
+ /// to construct another buffer.
+ void Clear()
+ {
+ ClearOffsets();
+ buf_.clear();
+ nested = false;
+ finished = false;
+ minalign_ = 1;
+ if (string_pool)
+ string_pool->clear();
+ }
+
+ /// @brief The current size of the serialized buffer, counting from the end.
+ /// @return Returns an `uoffset_t` with the current size of the buffer.
+ uoffset_t GetSize() const { return buf_.size(); }
+
+ /// @brief Get the serialized buffer (after you call `Finish()`).
+ /// @return Returns an `uint8_t` pointer to the FlatBuffer data inside the
+ /// buffer.
+ uint8_t *GetBufferPointer() const
+ {
+ Finished();
+ return buf_.data();
+ }
+
+ /// @brief Get the serialized buffer (after you call `Finish()`) as a span.
+ /// @return Returns a constructed flatbuffers::span that is a view over the
+ /// FlatBuffer data inside the buffer.
+ flatbuffers::span<uint8_t> GetBufferSpan() const
+ {
+ Finished();
+ return flatbuffers::span<uint8_t>(buf_.data(), buf_.size());
+ }
+
+ /// @brief Get a pointer to an unfinished buffer.
+ /// @return Returns a `uint8_t` pointer to the unfinished buffer.
+ uint8_t *GetCurrentBufferPointer() const { return buf_.data(); }
+
+ /// @brief Get the released pointer to the serialized buffer.
+ /// @warning Do NOT attempt to use this FlatBufferBuilder afterwards!
+ /// @return A `FlatBuffer` that owns the buffer and its allocator and
+ /// behaves similar to a `unique_ptr` with a deleter.
+ FLATBUFFERS_ATTRIBUTE(deprecated("use Release() instead"))
+ DetachedBuffer ReleaseBufferPointer()
+ {
+ Finished();
+ return buf_.release();
+ }
+
+ /// @brief Get the released DetachedBuffer.
+ /// @return A `DetachedBuffer` that owns the buffer and its allocator.
+ DetachedBuffer Release()
+ {
+ Finished();
+ return buf_.release();
+ }
+
+ /// @brief Get the released pointer to the serialized buffer.
+ /// @param size The size of the memory block containing
+ /// the serialized `FlatBuffer`.
+ /// @param offset The offset from the released pointer where the finished
+ /// `FlatBuffer` starts.
+ /// @return A raw pointer to the start of the memory block containing
+ /// the serialized `FlatBuffer`.
+ /// @remark If the allocator is owned, it gets deleted when the destructor is
+ /// called..
+ uint8_t *ReleaseRaw(size_t &size, size_t &offset)
+ {
+ Finished();
+ return buf_.release_raw(size, offset);
+ }
+
+ /// @brief get the minimum alignment this buffer needs to be accessed
+ /// properly. This is only known once all elements have been written (after
+ /// you call Finish()). You can use this information if you need to embed
+ /// a FlatBuffer in some other buffer, such that you can later read it
+ /// without first having to copy it into its own buffer.
+ size_t GetBufferMinAlignment() const
+ {
+ Finished();
+ return minalign_;
+ }
+
+ /// @cond FLATBUFFERS_INTERNAL
+ void Finished() const
+ {
+ // If you get this assert, you're attempting to get access a buffer
+ // which hasn't been finished yet. Be sure to call
+ // FlatBufferBuilder::Finish with your root table.
+ // If you really need to access an unfinished buffer, call
+ // GetCurrentBufferPointer instead.
+ FLATBUFFERS_ASSERT(finished);
+ }
+ /// @endcond
+
+ /// @brief In order to save space, fields that are set to their default value
+ /// don't get serialized into the buffer.
+ /// @param[in] fd When set to `true`, always serializes default values that
+ /// are set. Optional fields which are not set explicitly, will still not be
+ /// serialized.
+ void ForceDefaults(bool fd) { force_defaults_ = fd; }
+
+ /// @brief By default vtables are deduped in order to save space.
+ /// @param[in] dedup When set to `true`, dedup vtables.
+ void DedupVtables(bool dedup) { dedup_vtables_ = dedup; }
+
+ /// @cond FLATBUFFERS_INTERNAL
+ void Pad(size_t num_bytes) { buf_.fill(num_bytes); }
+
+ void TrackMinAlign(size_t elem_size)
+ {
+ if (elem_size > minalign_)
+ minalign_ = elem_size;
+ }
+
+ void Align(size_t elem_size)
+ {
+ TrackMinAlign(elem_size);
+ buf_.fill(PaddingBytes(buf_.size(), elem_size));
+ }
+
+ void PushFlatBuffer(const uint8_t *bytes, size_t size)
+ {
+ PushBytes(bytes, size);
+ finished = true;
+ }
+
+ void PushBytes(const uint8_t *bytes, size_t size) { buf_.push(bytes, size); }
+
+ void PopBytes(size_t amount) { buf_.pop(amount); }
+
+ template <typename T> void AssertScalarT()
+ {
+ // The code assumes power of 2 sizes and endian-swap-ability.
+ static_assert(flatbuffers::is_scalar<T>::value, "T must be a scalar type");
+ }
+
+ // Write a single aligned scalar to the buffer
+ template <typename T> uoffset_t PushElement(T element)
+ {
+ AssertScalarT<T>();
+ T litle_endian_element = EndianScalar(element);
+ Align(sizeof(T));
+ buf_.push_small(litle_endian_element);
+ return GetSize();
+ }
+
+ template <typename T> uoffset_t PushElement(Offset<T> off)
+ {
+ // Special case for offsets: see ReferTo below.
+ return PushElement(ReferTo(off.o));
+ }
+
+ // When writing fields, we track where they are, so we can create correct
+ // vtables later.
+ void TrackField(voffset_t field, uoffset_t off)
+ {
+ FieldLoc fl = {off, field};
+ buf_.scratch_push_small(fl);
+ num_field_loc++;
+ max_voffset_ = (std::max)(max_voffset_, field);
+ }
+
+ // Like PushElement, but additionally tracks the field this represents.
+ template <typename T> void AddElement(voffset_t field, T e, T def)
+ {
+ // We don't serialize values equal to the default.
+ if (IsTheSameAs(e, def) && !force_defaults_)
+ return;
+ auto off = PushElement(e);
+ TrackField(field, off);
+ }
+
+ template <typename T> void AddElement(voffset_t field, T e)
+ {
+ auto off = PushElement(e);
+ TrackField(field, off);
+ }
+
+ template <typename T> void AddOffset(voffset_t field, Offset<T> off)
+ {
+ if (off.IsNull())
+ return; // Don't store.
+ AddElement(field, ReferTo(off.o), static_cast<uoffset_t>(0));
+ }
+
+ template <typename T> void AddStruct(voffset_t field, const T *structptr)
+ {
+ if (!structptr)
+ return; // Default, don't store.
+ Align(AlignOf<T>());
+ buf_.push_small(*structptr);
+ TrackField(field, GetSize());
+ }
+
+ void AddStructOffset(voffset_t field, uoffset_t off) { TrackField(field, off); }
+
+ // Offsets initially are relative to the end of the buffer (downwards).
+ // This function converts them to be relative to the current location
+ // in the buffer (when stored here), pointing upwards.
+ uoffset_t ReferTo(uoffset_t off)
+ {
+ // Align to ensure GetSize() below is correct.
+ Align(sizeof(uoffset_t));
+ // Offset must refer to something already in buffer.
+ FLATBUFFERS_ASSERT(off && off <= GetSize());
+ return GetSize() - off + static_cast<uoffset_t>(sizeof(uoffset_t));
+ }
+
+ void NotNested()
+ {
+ // If you hit this, you're trying to construct a Table/Vector/String
+ // during the construction of its parent table (between the MyTableBuilder
+ // and table.Finish().
+ // Move the creation of these sub-objects to above the MyTableBuilder to
+ // not get this assert.
+ // Ignoring this assert may appear to work in simple cases, but the reason
+ // it is here is that storing objects in-line may cause vtable offsets
+ // to not fit anymore. It also leads to vtable duplication.
+ FLATBUFFERS_ASSERT(!nested);
+ // If you hit this, fields were added outside the scope of a table.
+ FLATBUFFERS_ASSERT(!num_field_loc);
+ }
+
+ // From generated code (or from the parser), we call StartTable/EndTable
+ // with a sequence of AddElement calls in between.
+ uoffset_t StartTable()
+ {
+ NotNested();
+ nested = true;
+ return GetSize();
+ }
+
+ // This finishes one serialized object by generating the vtable if it's a
+ // table, comparing it against existing vtables, and writing the
+ // resulting vtable offset.
+ uoffset_t EndTable(uoffset_t start)
+ {
+ // If you get this assert, a corresponding StartTable wasn't called.
+ FLATBUFFERS_ASSERT(nested);
+ // Write the vtable offset, which is the start of any Table.
+ // We fill it's value later.
+ auto vtableoffsetloc = PushElement<soffset_t>(0);
+ // Write a vtable, which consists entirely of voffset_t elements.
+ // It starts with the number of offsets, followed by a type id, followed
+ // by the offsets themselves. In reverse:
+ // Include space for the last offset and ensure empty tables have a
+ // minimum size.
+ max_voffset_ =
+ (std::max)(static_cast<voffset_t>(max_voffset_ + sizeof(voffset_t)), FieldIndexToOffset(0));
+ buf_.fill_big(max_voffset_);
+ auto table_object_size = vtableoffsetloc - start;
+ // Vtable use 16bit offsets.
+ FLATBUFFERS_ASSERT(table_object_size < 0x10000);
+ WriteScalar<voffset_t>(buf_.data() + sizeof(voffset_t),
+ static_cast<voffset_t>(table_object_size));
+ WriteScalar<voffset_t>(buf_.data(), max_voffset_);
+ // Write the offsets into the table
+ for (auto it = buf_.scratch_end() - num_field_loc * sizeof(FieldLoc); it < buf_.scratch_end();
+ it += sizeof(FieldLoc))
+ {
+ auto field_location = reinterpret_cast<FieldLoc *>(it);
+ auto pos = static_cast<voffset_t>(vtableoffsetloc - field_location->off);
+ // If this asserts, it means you've set a field twice.
+ FLATBUFFERS_ASSERT(!ReadScalar<voffset_t>(buf_.data() + field_location->id));
+ WriteScalar<voffset_t>(buf_.data() + field_location->id, pos);
+ }
+ ClearOffsets();
+ auto vt1 = reinterpret_cast<voffset_t *>(buf_.data());
+ auto vt1_size = ReadScalar<voffset_t>(vt1);
+ auto vt_use = GetSize();
+ // See if we already have generated a vtable with this exact same
+ // layout before. If so, make it point to the old one, remove this one.
+ if (dedup_vtables_)
+ {
+ for (auto it = buf_.scratch_data(); it < buf_.scratch_end(); it += sizeof(uoffset_t))
+ {
+ auto vt_offset_ptr = reinterpret_cast<uoffset_t *>(it);
+ auto vt2 = reinterpret_cast<voffset_t *>(buf_.data_at(*vt_offset_ptr));
+ auto vt2_size = ReadScalar<voffset_t>(vt2);
+ if (vt1_size != vt2_size || 0 != memcmp(vt2, vt1, vt1_size))
+ continue;
+ vt_use = *vt_offset_ptr;
+ buf_.pop(GetSize() - vtableoffsetloc);
+ break;
+ }
+ }
+ // If this is a new vtable, remember it.
+ if (vt_use == GetSize())
+ {
+ buf_.scratch_push_small(vt_use);
+ }
+ // Fill the vtable offset we created above.
+ // The offset points from the beginning of the object to where the
+ // vtable is stored.
+ // Offsets default direction is downward in memory for future format
+ // flexibility (storing all vtables at the start of the file).
+ WriteScalar(buf_.data_at(vtableoffsetloc),
+ static_cast<soffset_t>(vt_use) - static_cast<soffset_t>(vtableoffsetloc));
+
+ nested = false;
+ return vtableoffsetloc;
+ }
+
+ FLATBUFFERS_ATTRIBUTE(deprecated("call the version above instead"))
+ uoffset_t EndTable(uoffset_t start, voffset_t /*numfields*/) { return EndTable(start); }
+
+ // This checks a required field has been set in a given table that has
+ // just been constructed.
+ template <typename T> void Required(Offset<T> table, voffset_t field);
+
+ uoffset_t StartStruct(size_t alignment)
+ {
+ Align(alignment);
+ return GetSize();
+ }
+
+ uoffset_t EndStruct() { return GetSize(); }
+
+ void ClearOffsets()
+ {
+ buf_.scratch_pop(num_field_loc * sizeof(FieldLoc));
+ num_field_loc = 0;
+ max_voffset_ = 0;
+ }
+
+ // Aligns such that when "len" bytes are written, an object can be written
+ // after it with "alignment" without padding.
+ void PreAlign(size_t len, size_t alignment)
+ {
+ TrackMinAlign(alignment);
+ buf_.fill(PaddingBytes(GetSize() + len, alignment));
+ }
+ template <typename T> void PreAlign(size_t len)
+ {
+ AssertScalarT<T>();
+ PreAlign(len, sizeof(T));
+ }
+ /// @endcond
+
+ /// @brief Store a string in the buffer, which can contain any binary data.
+ /// @param[in] str A const char pointer to the data to be stored as a string.
+ /// @param[in] len The number of bytes that should be stored from `str`.
+ /// @return Returns the offset in the buffer where the string starts.
+ Offset<String> CreateString(const char *str, size_t len)
+ {
+ NotNested();
+ PreAlign<uoffset_t>(len + 1); // Always 0-terminated.
+ buf_.fill(1);
+ PushBytes(reinterpret_cast<const uint8_t *>(str), len);
+ PushElement(static_cast<uoffset_t>(len));
+ return Offset<String>(GetSize());
+ }
+
+ /// @brief Store a string in the buffer, which is null-terminated.
+ /// @param[in] str A const char pointer to a C-string to add to the buffer.
+ /// @return Returns the offset in the buffer where the string starts.
+ Offset<String> CreateString(const char *str) { return CreateString(str, strlen(str)); }
+
+ /// @brief Store a string in the buffer, which is null-terminated.
+ /// @param[in] str A char pointer to a C-string to add to the buffer.
+ /// @return Returns the offset in the buffer where the string starts.
+ Offset<String> CreateString(char *str) { return CreateString(str, strlen(str)); }
+
+ /// @brief Store a string in the buffer, which can contain any binary data.
+ /// @param[in] str A const reference to a std::string to store in the buffer.
+ /// @return Returns the offset in the buffer where the string starts.
+ Offset<String> CreateString(const std::string &str)
+ {
+ return CreateString(str.c_str(), str.length());
+ }
+#ifdef FLATBUFFERS_HAS_STRING_VIEW
+ /// @brief Store a string in the buffer, which can contain any binary data.
+ /// @param[in] str A const string_view to copy in to the buffer.
+ /// @return Returns the offset in the buffer where the string starts.
+ Offset<String> CreateString(flatbuffers::string_view str)
+ {
+ return CreateString(str.data(), str.size());
+ }
+#endif // FLATBUFFERS_HAS_STRING_VIEW
+ // clang-format on
+
+ /// @brief Store a string in the buffer, which can contain any binary data.
+ /// @param[in] str A const pointer to a `String` struct to add to the buffer.
+ /// @return Returns the offset in the buffer where the string starts
+ Offset<String> CreateString(const String *str)
+ {
+ return str ? CreateString(str->c_str(), str->size()) : 0;
+ }
+
+ /// @brief Store a string in the buffer, which can contain any binary data.
+ /// @param[in] str A const reference to a std::string like type with support
+ /// of T::c_str() and T::length() to store in the buffer.
+ /// @return Returns the offset in the buffer where the string starts.
+ template <typename T> Offset<String> CreateString(const T &str)
+ {
+ return CreateString(str.c_str(), str.length());
+ }
+
+ /// @brief Store a string in the buffer, which can contain any binary data.
+ /// If a string with this exact contents has already been serialized before,
+ /// instead simply returns the offset of the existing string.
+ /// @param[in] str A const char pointer to the data to be stored as a string.
+ /// @param[in] len The number of bytes that should be stored from `str`.
+ /// @return Returns the offset in the buffer where the string starts.
+ Offset<String> CreateSharedString(const char *str, size_t len)
+ {
+ if (!string_pool)
+ string_pool = new StringOffsetMap(StringOffsetCompare(buf_));
+ auto size_before_string = buf_.size();
+ // Must first serialize the string, since the set is all offsets into
+ // buffer.
+ auto off = CreateString(str, len);
+ auto it = string_pool->find(off);
+ // If it exists we reuse existing serialized data!
+ if (it != string_pool->end())
+ {
+ // We can remove the string we serialized.
+ buf_.pop(buf_.size() - size_before_string);
+ return *it;
+ }
+ // Record this string for future use.
+ string_pool->insert(off);
+ return off;
+ }
+
+#ifdef FLATBUFFERS_HAS_STRING_VIEW
+ /// @brief Store a string in the buffer, which can contain any binary data.
+ /// If a string with this exact contents has already been serialized before,
+ /// instead simply returns the offset of the existing string.
+ /// @param[in] str A const std::string_view to store in the buffer.
+ /// @return Returns the offset in the buffer where the string starts
+ Offset<String> CreateSharedString(const flatbuffers::string_view str)
+ {
+ return CreateSharedString(str.data(), str.size());
+ }
+#else
+ /// @brief Store a string in the buffer, which null-terminated.
+ /// If a string with this exact contents has already been serialized before,
+ /// instead simply returns the offset of the existing string.
+ /// @param[in] str A const char pointer to a C-string to add to the buffer.
+ /// @return Returns the offset in the buffer where the string starts.
+ Offset<String> CreateSharedString(const char *str)
+ {
+ return CreateSharedString(str, strlen(str));
+ }
+
+ /// @brief Store a string in the buffer, which can contain any binary data.
+ /// If a string with this exact contents has already been serialized before,
+ /// instead simply returns the offset of the existing string.
+ /// @param[in] str A const reference to a std::string to store in the buffer.
+ /// @return Returns the offset in the buffer where the string starts.
+ Offset<String> CreateSharedString(const std::string &str)
+ {
+ return CreateSharedString(str.c_str(), str.length());
+ }
+#endif
+
+ /// @brief Store a string in the buffer, which can contain any binary data.
+ /// If a string with this exact contents has already been serialized before,
+ /// instead simply returns the offset of the existing string.
+ /// @param[in] str A const pointer to a `String` struct to add to the buffer.
+ /// @return Returns the offset in the buffer where the string starts
+ Offset<String> CreateSharedString(const String *str)
+ {
+ return CreateSharedString(str->c_str(), str->size());
+ }
+
+ /// @cond FLATBUFFERS_INTERNAL
+ uoffset_t EndVector(size_t len)
+ {
+ FLATBUFFERS_ASSERT(nested); // Hit if no corresponding StartVector.
+ nested = false;
+ return PushElement(static_cast<uoffset_t>(len));
+ }
+
+ void StartVector(size_t len, size_t elemsize)
+ {
+ NotNested();
+ nested = true;
+ PreAlign<uoffset_t>(len * elemsize);
+ PreAlign(len * elemsize, elemsize); // Just in case elemsize > uoffset_t.
+ }
+
+ // Call this right before StartVector/CreateVector if you want to force the
+ // alignment to be something different than what the element size would
+ // normally dictate.
+ // This is useful when storing a nested_flatbuffer in a vector of bytes,
+ // or when storing SIMD floats, etc.
+ void ForceVectorAlignment(size_t len, size_t elemsize, size_t alignment)
+ {
+ FLATBUFFERS_ASSERT(VerifyAlignmentRequirements(alignment));
+ PreAlign(len * elemsize, alignment);
+ }
+
+ // Similar to ForceVectorAlignment but for String fields.
+ void ForceStringAlignment(size_t len, size_t alignment)
+ {
+ FLATBUFFERS_ASSERT(VerifyAlignmentRequirements(alignment));
+ PreAlign((len + 1) * sizeof(char), alignment);
+ }
+
+ /// @endcond
+
+ /// @brief Serialize an array into a FlatBuffer `vector`.
+ /// @tparam T The data type of the array elements.
+ /// @param[in] v A pointer to the array of type `T` to serialize into the
+ /// buffer as a `vector`.
+ /// @param[in] len The number of elements to serialize.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template <typename T> Offset<Vector<T>> CreateVector(const T *v, size_t len)
+ {
+ // If this assert hits, you're specifying a template argument that is
+ // causing the wrong overload to be selected, remove it.
+ AssertScalarT<T>();
+ StartVector(len, sizeof(T));
+ if (len == 0)
+ {
+ return Offset<Vector<T>>(EndVector(len));
+ }
+
+#if FLATBUFFERS_LITTLEENDIAN
+ PushBytes(reinterpret_cast<const uint8_t *>(v), len * sizeof(T));
+#else
+ if (sizeof(T) == 1)
+ {
+ PushBytes(reinterpret_cast<const uint8_t *>(v), len);
+ }
+ else
+ {
+ for (auto i = len; i > 0;)
+ {
+ PushElement(v[--i]);
+ }
+ }
+#endif
+ // clang-format on
+ return Offset<Vector<T>>(EndVector(len));
+ }
+
+ template <typename T> Offset<Vector<Offset<T>>> CreateVector(const Offset<T> *v, size_t len)
+ {
+ StartVector(len, sizeof(Offset<T>));
+ for (auto i = len; i > 0;)
+ {
+ PushElement(v[--i]);
+ }
+ return Offset<Vector<Offset<T>>>(EndVector(len));
+ }
+
+ /// @brief Serialize a `std::vector` into a FlatBuffer `vector`.
+ /// @tparam T The data type of the `std::vector` elements.
+ /// @param v A const reference to the `std::vector` to serialize into the
+ /// buffer as a `vector`.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template <typename T> Offset<Vector<T>> CreateVector(const std::vector<T> &v)
+ {
+ return CreateVector(data(v), v.size());
+ }
+
+ // vector<bool> may be implemented using a bit-set, so we can't access it as
+ // an array. Instead, read elements manually.
+ // Background: https://isocpp.org/blog/2012/11/on-vectorbool
+ Offset<Vector<uint8_t>> CreateVector(const std::vector<bool> &v)
+ {
+ StartVector(v.size(), sizeof(uint8_t));
+ for (auto i = v.size(); i > 0;)
+ {
+ PushElement(static_cast<uint8_t>(v[--i]));
+ }
+ return Offset<Vector<uint8_t>>(EndVector(v.size()));
+ }
+
+#ifndef FLATBUFFERS_CPP98_STL
+ /// @brief Serialize values returned by a function into a FlatBuffer `vector`.
+ /// This is a convenience function that takes care of iteration for you.
+ /// @tparam T The data type of the `std::vector` elements.
+ /// @param f A function that takes the current iteration 0..vector_size-1 and
+ /// returns any type that you can construct a FlatBuffers vector out of.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template <typename T>
+ Offset<Vector<T>> CreateVector(size_t vector_size, const std::function<T(size_t i)> &f)
+ {
+ std::vector<T> elems(vector_size);
+ for (size_t i = 0; i < vector_size; i++)
+ elems[i] = f(i);
+ return CreateVector(elems);
+ }
+#endif
+ // clang-format on
+
+ /// @brief Serialize values returned by a function into a FlatBuffer `vector`.
+ /// This is a convenience function that takes care of iteration for you.
+ /// @tparam T The data type of the `std::vector` elements.
+ /// @param f A function that takes the current iteration 0..vector_size-1,
+ /// and the state parameter returning any type that you can construct a
+ /// FlatBuffers vector out of.
+ /// @param state State passed to f.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template <typename T, typename F, typename S>
+ Offset<Vector<T>> CreateVector(size_t vector_size, F f, S *state)
+ {
+ std::vector<T> elems(vector_size);
+ for (size_t i = 0; i < vector_size; i++)
+ elems[i] = f(i, state);
+ return CreateVector(elems);
+ }
+
+ /// @brief Serialize a `std::vector<std::string>` into a FlatBuffer `vector`.
+ /// This is a convenience function for a common case.
+ /// @param v A const reference to the `std::vector` to serialize into the
+ /// buffer as a `vector`.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ Offset<Vector<Offset<String>>> CreateVectorOfStrings(const std::vector<std::string> &v)
+ {
+ std::vector<Offset<String>> offsets(v.size());
+ for (size_t i = 0; i < v.size(); i++)
+ offsets[i] = CreateString(v[i]);
+ return CreateVector(offsets);
+ }
+
+ /// @brief Serialize an array of structs into a FlatBuffer `vector`.
+ /// @tparam T The data type of the struct array elements.
+ /// @param[in] v A pointer to the array of type `T` to serialize into the
+ /// buffer as a `vector`.
+ /// @param[in] len The number of elements to serialize.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template <typename T> Offset<Vector<const T *>> CreateVectorOfStructs(const T *v, size_t len)
+ {
+ StartVector(len * sizeof(T) / AlignOf<T>(), AlignOf<T>());
+ PushBytes(reinterpret_cast<const uint8_t *>(v), sizeof(T) * len);
+ return Offset<Vector<const T *>>(EndVector(len));
+ }
+
+ /// @brief Serialize an array of native structs into a FlatBuffer `vector`.
+ /// @tparam T The data type of the struct array elements.
+ /// @tparam S The data type of the native struct array elements.
+ /// @param[in] v A pointer to the array of type `S` to serialize into the
+ /// buffer as a `vector`.
+ /// @param[in] len The number of elements to serialize.
+ /// @param[in] pack_func Pointer to a function to convert the native struct
+ /// to the FlatBuffer struct.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template <typename T, typename S>
+ Offset<Vector<const T *>> CreateVectorOfNativeStructs(const S *v, size_t len,
+ T((*const pack_func)(const S &)))
+ {
+ FLATBUFFERS_ASSERT(pack_func);
+ std::vector<T> vv(len);
+ std::transform(v, v + len, vv.begin(), pack_func);
+ return CreateVectorOfStructs<T>(data(vv), vv.size());
+ }
+
+ /// @brief Serialize an array of native structs into a FlatBuffer `vector`.
+ /// @tparam T The data type of the struct array elements.
+ /// @tparam S The data type of the native struct array elements.
+ /// @param[in] v A pointer to the array of type `S` to serialize into the
+ /// buffer as a `vector`.
+ /// @param[in] len The number of elements to serialize.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template <typename T, typename S>
+ Offset<Vector<const T *>> CreateVectorOfNativeStructs(const S *v, size_t len)
+ {
+ extern T Pack(const S &);
+ return CreateVectorOfNativeStructs(v, len, Pack);
+ }
+
+#ifndef FLATBUFFERS_CPP98_STL
+ /// @brief Serialize an array of structs into a FlatBuffer `vector`.
+ /// @tparam T The data type of the struct array elements.
+ /// @param[in] filler A function that takes the current iteration 0..vector_size-1
+ /// and a pointer to the struct that must be filled.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ /// This is mostly useful when flatbuffers are generated with mutation
+ /// accessors.
+ template <typename T>
+ Offset<Vector<const T *>> CreateVectorOfStructs(size_t vector_size,
+ const std::function<void(size_t i, T *)> &filler)
+ {
+ T *structs = StartVectorOfStructs<T>(vector_size);
+ for (size_t i = 0; i < vector_size; i++)
+ {
+ filler(i, structs);
+ structs++;
+ }
+ return EndVectorOfStructs<T>(vector_size);
+ }
+#endif
+ // clang-format on
+
+ /// @brief Serialize an array of structs into a FlatBuffer `vector`.
+ /// @tparam T The data type of the struct array elements.
+ /// @param[in] f A function that takes the current iteration 0..vector_size-1,
+ /// a pointer to the struct that must be filled and the state argument.
+ /// @param[in] state Arbitrary state to pass to f.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ /// This is mostly useful when flatbuffers are generated with mutation
+ /// accessors.
+ template <typename T, typename F, typename S>
+ Offset<Vector<const T *>> CreateVectorOfStructs(size_t vector_size, F f, S *state)
+ {
+ T *structs = StartVectorOfStructs<T>(vector_size);
+ for (size_t i = 0; i < vector_size; i++)
+ {
+ f(i, structs, state);
+ structs++;
+ }
+ return EndVectorOfStructs<T>(vector_size);
+ }
+
+ /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`.
+ /// @tparam T The data type of the `std::vector` struct elements.
+ /// @param[in] v A const reference to the `std::vector` of structs to
+ /// serialize into the buffer as a `vector`.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template <typename T, typename Alloc>
+ Offset<Vector<const T *>> CreateVectorOfStructs(const std::vector<T, Alloc> &v)
+ {
+ return CreateVectorOfStructs(data(v), v.size());
+ }
+
+ /// @brief Serialize a `std::vector` of native structs into a FlatBuffer
+ /// `vector`.
+ /// @tparam T The data type of the `std::vector` struct elements.
+ /// @tparam S The data type of the `std::vector` native struct elements.
+ /// @param[in] v A const reference to the `std::vector` of structs to
+ /// serialize into the buffer as a `vector`.
+ /// @param[in] pack_func Pointer to a function to convert the native struct
+ /// to the FlatBuffer struct.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template <typename T, typename S>
+ Offset<Vector<const T *>> CreateVectorOfNativeStructs(const std::vector<S> &v,
+ T((*const pack_func)(const S &)))
+ {
+ return CreateVectorOfNativeStructs<T, S>(data(v), v.size(), pack_func);
+ }
+
+ /// @brief Serialize a `std::vector` of native structs into a FlatBuffer
+ /// `vector`.
+ /// @tparam T The data type of the `std::vector` struct elements.
+ /// @tparam S The data type of the `std::vector` native struct elements.
+ /// @param[in] v A const reference to the `std::vector` of structs to
+ /// serialize into the buffer as a `vector`.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template <typename T, typename S>
+ Offset<Vector<const T *>> CreateVectorOfNativeStructs(const std::vector<S> &v)
+ {
+ return CreateVectorOfNativeStructs<T, S>(data(v), v.size());
+ }
+
+ /// @cond FLATBUFFERS_INTERNAL
+ template <typename T> struct StructKeyComparator
+ {
+ bool operator()(const T &a, const T &b) const { return a.KeyCompareLessThan(&b); }
+
+ FLATBUFFERS_DELETE_FUNC(StructKeyComparator &operator=(const StructKeyComparator &));
+ };
+ /// @endcond
+
+ /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`
+ /// in sorted order.
+ /// @tparam T The data type of the `std::vector` struct elements.
+ /// @param[in] v A const reference to the `std::vector` of structs to
+ /// serialize into the buffer as a `vector`.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template <typename T> Offset<Vector<const T *>> CreateVectorOfSortedStructs(std::vector<T> *v)
+ {
+ return CreateVectorOfSortedStructs(data(*v), v->size());
+ }
+
+ /// @brief Serialize a `std::vector` of native structs into a FlatBuffer
+ /// `vector` in sorted order.
+ /// @tparam T The data type of the `std::vector` struct elements.
+ /// @tparam S The data type of the `std::vector` native struct elements.
+ /// @param[in] v A const reference to the `std::vector` of structs to
+ /// serialize into the buffer as a `vector`.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template <typename T, typename S>
+ Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(std::vector<S> *v)
+ {
+ return CreateVectorOfSortedNativeStructs<T, S>(data(*v), v->size());
+ }
+
+ /// @brief Serialize an array of structs into a FlatBuffer `vector` in sorted
+ /// order.
+ /// @tparam T The data type of the struct array elements.
+ /// @param[in] v A pointer to the array of type `T` to serialize into the
+ /// buffer as a `vector`.
+ /// @param[in] len The number of elements to serialize.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template <typename T> Offset<Vector<const T *>> CreateVectorOfSortedStructs(T *v, size_t len)
+ {
+ std::sort(v, v + len, StructKeyComparator<T>());
+ return CreateVectorOfStructs(v, len);
+ }
+
+ /// @brief Serialize an array of native structs into a FlatBuffer `vector` in
+ /// sorted order.
+ /// @tparam T The data type of the struct array elements.
+ /// @tparam S The data type of the native struct array elements.
+ /// @param[in] v A pointer to the array of type `S` to serialize into the
+ /// buffer as a `vector`.
+ /// @param[in] len The number of elements to serialize.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template <typename T, typename S>
+ Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(S *v, size_t len)
+ {
+ extern T Pack(const S &);
+ typedef T (*Pack_t)(const S &);
+ std::vector<T> vv(len);
+ std::transform(v, v + len, vv.begin(), static_cast<Pack_t &>(Pack));
+ return CreateVectorOfSortedStructs<T>(vv, len);
+ }
+
+ /// @cond FLATBUFFERS_INTERNAL
+ template <typename T> struct TableKeyComparator
+ {
+ TableKeyComparator(vector_downward &buf) : buf_(buf) {}
+ TableKeyComparator(const TableKeyComparator &other) : buf_(other.buf_) {}
+ bool operator()(const Offset<T> &a, const Offset<T> &b) const
+ {
+ auto table_a = reinterpret_cast<T *>(buf_.data_at(a.o));
+ auto table_b = reinterpret_cast<T *>(buf_.data_at(b.o));
+ return table_a->KeyCompareLessThan(table_b);
+ }
+ vector_downward &buf_;
+
+ private:
+ FLATBUFFERS_DELETE_FUNC(TableKeyComparator &operator=(const TableKeyComparator &other));
+ };
+ /// @endcond
+
+ /// @brief Serialize an array of `table` offsets as a `vector` in the buffer
+ /// in sorted order.
+ /// @tparam T The data type that the offset refers to.
+ /// @param[in] v An array of type `Offset<T>` that contains the `table`
+ /// offsets to store in the buffer in sorted order.
+ /// @param[in] len The number of elements to store in the `vector`.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template <typename T>
+ Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(Offset<T> *v, size_t len)
+ {
+ std::sort(v, v + len, TableKeyComparator<T>(buf_));
+ return CreateVector(v, len);
+ }
+
+ /// @brief Serialize an array of `table` offsets as a `vector` in the buffer
+ /// in sorted order.
+ /// @tparam T The data type that the offset refers to.
+ /// @param[in] v An array of type `Offset<T>` that contains the `table`
+ /// offsets to store in the buffer in sorted order.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template <typename T>
+ Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(std::vector<Offset<T>> *v)
+ {
+ return CreateVectorOfSortedTables(data(*v), v->size());
+ }
+
+ /// @brief Specialized version of `CreateVector` for non-copying use cases.
+ /// Write the data any time later to the returned buffer pointer `buf`.
+ /// @param[in] len The number of elements to store in the `vector`.
+ /// @param[in] elemsize The size of each element in the `vector`.
+ /// @param[out] buf A pointer to a `uint8_t` pointer that can be
+ /// written to at a later time to serialize the data into a `vector`
+ /// in the buffer.
+ uoffset_t CreateUninitializedVector(size_t len, size_t elemsize, uint8_t **buf)
+ {
+ NotNested();
+ StartVector(len, elemsize);
+ buf_.make_space(len * elemsize);
+ auto vec_start = GetSize();
+ auto vec_end = EndVector(len);
+ *buf = buf_.data_at(vec_start);
+ return vec_end;
+ }
+
+ /// @brief Specialized version of `CreateVector` for non-copying use cases.
+ /// Write the data any time later to the returned buffer pointer `buf`.
+ /// @tparam T The data type of the data that will be stored in the buffer
+ /// as a `vector`.
+ /// @param[in] len The number of elements to store in the `vector`.
+ /// @param[out] buf A pointer to a pointer of type `T` that can be
+ /// written to at a later time to serialize the data into a `vector`
+ /// in the buffer.
+ template <typename T> Offset<Vector<T>> CreateUninitializedVector(size_t len, T **buf)
+ {
+ AssertScalarT<T>();
+ return CreateUninitializedVector(len, sizeof(T), reinterpret_cast<uint8_t **>(buf));
+ }
+
+ template <typename T>
+ Offset<Vector<const T *>> CreateUninitializedVectorOfStructs(size_t len, T **buf)
+ {
+ return CreateUninitializedVector(len, sizeof(T), reinterpret_cast<uint8_t **>(buf));
+ }
+
+ // @brief Create a vector of scalar type T given as input a vector of scalar
+ // type U, useful with e.g. pre "enum class" enums, or any existing scalar
+ // data of the wrong type.
+ template <typename T, typename U> Offset<Vector<T>> CreateVectorScalarCast(const U *v, size_t len)
+ {
+ AssertScalarT<T>();
+ AssertScalarT<U>();
+ StartVector(len, sizeof(T));
+ for (auto i = len; i > 0;)
+ {
+ PushElement(static_cast<T>(v[--i]));
+ }
+ return Offset<Vector<T>>(EndVector(len));
+ }
+
+ /// @brief Write a struct by itself, typically to be part of a union.
+ template <typename T> Offset<const T *> CreateStruct(const T &structobj)
+ {
+ NotNested();
+ Align(AlignOf<T>());
+ buf_.push_small(structobj);
+ return Offset<const T *>(GetSize());
+ }
+
+ /// @brief The length of a FlatBuffer file header.
+ static const size_t kFileIdentifierLength = 4;
+
+ /// @brief Finish serializing a buffer by writing the root offset.
+ /// @param[in] file_identifier If a `file_identifier` is given, the buffer
+ /// will be prefixed with a standard FlatBuffers file header.
+ template <typename T> void Finish(Offset<T> root, const char *file_identifier = nullptr)
+ {
+ Finish(root.o, file_identifier, false);
+ }
+
+ /// @brief Finish a buffer with a 32 bit size field pre-fixed (size of the
+ /// buffer following the size field). These buffers are NOT compatible
+ /// with standard buffers created by Finish, i.e. you can't call GetRoot
+ /// on them, you have to use GetSizePrefixedRoot instead.
+ /// All >32 bit quantities in this buffer will be aligned when the whole
+ /// size pre-fixed buffer is aligned.
+ /// These kinds of buffers are useful for creating a stream of FlatBuffers.
+ template <typename T>
+ void FinishSizePrefixed(Offset<T> root, const char *file_identifier = nullptr)
+ {
+ Finish(root.o, file_identifier, true);
+ }
+
+ void SwapBufAllocator(FlatBufferBuilder &other) { buf_.swap_allocator(other.buf_); }
+
+protected:
+ // You shouldn't really be copying instances of this class.
+ FlatBufferBuilder(const FlatBufferBuilder &);
+ FlatBufferBuilder &operator=(const FlatBufferBuilder &);
+
+ void Finish(uoffset_t root, const char *file_identifier, bool size_prefix)
+ {
+ NotNested();
+ buf_.clear_scratch();
+ // This will cause the whole buffer to be aligned.
+ PreAlign((size_prefix ? sizeof(uoffset_t) : 0) + sizeof(uoffset_t) +
+ (file_identifier ? kFileIdentifierLength : 0),
+ minalign_);
+ if (file_identifier)
+ {
+ FLATBUFFERS_ASSERT(strlen(file_identifier) == kFileIdentifierLength);
+ PushBytes(reinterpret_cast<const uint8_t *>(file_identifier), kFileIdentifierLength);
+ }
+ PushElement(ReferTo(root)); // Location of root.
+ if (size_prefix)
+ {
+ PushElement(GetSize());
+ }
+ finished = true;
+ }
+
+ struct FieldLoc
+ {
+ uoffset_t off;
+ voffset_t id;
+ };
+
+ vector_downward buf_;
+
+ // Accumulating offsets of table members while it is being built.
+ // We store these in the scratch pad of buf_, after the vtable offsets.
+ uoffset_t num_field_loc;
+ // Track how much of the vtable is in use, so we can output the most compact
+ // possible vtable.
+ voffset_t max_voffset_;
+
+ // Ensure objects are not nested.
+ bool nested;
+
+ // Ensure the buffer is finished before it is being accessed.
+ bool finished;
+
+ size_t minalign_;
+
+ bool force_defaults_; // Serialize values equal to their defaults anyway.
+
+ bool dedup_vtables_;
+
+ struct StringOffsetCompare
+ {
+ StringOffsetCompare(const vector_downward &buf) : buf_(&buf) {}
+ bool operator()(const Offset<String> &a, const Offset<String> &b) const
+ {
+ auto stra = reinterpret_cast<const String *>(buf_->data_at(a.o));
+ auto strb = reinterpret_cast<const String *>(buf_->data_at(b.o));
+ return StringLessThan(stra->data(), stra->size(), strb->data(), strb->size());
+ }
+ const vector_downward *buf_;
+ };
+
+ // For use with CreateSharedString. Instantiated on first use only.
+ typedef std::set<Offset<String>, StringOffsetCompare> StringOffsetMap;
+ StringOffsetMap *string_pool;
+
+private:
+ // Allocates space for a vector of structures.
+ // Must be completed with EndVectorOfStructs().
+ template <typename T> T *StartVectorOfStructs(size_t vector_size)
+ {
+ StartVector(vector_size * sizeof(T) / AlignOf<T>(), AlignOf<T>());
+ return reinterpret_cast<T *>(buf_.make_space(vector_size * sizeof(T)));
+ }
+
+ // End the vector of structues in the flatbuffers.
+ // Vector should have previously be started with StartVectorOfStructs().
+ template <typename T> Offset<Vector<const T *>> EndVectorOfStructs(size_t vector_size)
+ {
+ return Offset<Vector<const T *>>(EndVector(vector_size));
+ }
+};
+/// @}
+
+/// @cond FLATBUFFERS_INTERNAL
+// Helpers to get a typed pointer to the root object contained in the buffer.
+template <typename T> T *GetMutableRoot(void *buf)
+{
+ EndianCheck();
+ return reinterpret_cast<T *>(reinterpret_cast<uint8_t *>(buf) +
+ EndianScalar(*reinterpret_cast<uoffset_t *>(buf)));
+}
+
+template <typename T> const T *GetRoot(const void *buf)
+{
+ return GetMutableRoot<T>(const_cast<void *>(buf));
+}
+
+template <typename T> const T *GetSizePrefixedRoot(const void *buf)
+{
+ return GetRoot<T>(reinterpret_cast<const uint8_t *>(buf) + sizeof(uoffset_t));
+}
+
+/// Helpers to get a typed pointer to objects that are currently being built.
+/// @warning Creating new objects will lead to reallocations and invalidates
+/// the pointer!
+template <typename T> T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset)
+{
+ return reinterpret_cast<T *>(fbb.GetCurrentBufferPointer() + fbb.GetSize() - offset.o);
+}
+
+template <typename T> const T *GetTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset)
+{
+ return GetMutableTemporaryPointer<T>(fbb, offset);
+}
+
+/// @brief Get a pointer to the the file_identifier section of the buffer.
+/// @return Returns a const char pointer to the start of the file_identifier
+/// characters in the buffer. The returned char * has length
+/// 'flatbuffers::FlatBufferBuilder::kFileIdentifierLength'.
+/// This function is UNDEFINED for FlatBuffers whose schema does not include
+/// a file_identifier (likely points at padding or the start of a the root
+/// vtable).
+inline const char *GetBufferIdentifier(const void *buf, bool size_prefixed = false)
+{
+ return reinterpret_cast<const char *>(buf) +
+ ((size_prefixed) ? 2 * sizeof(uoffset_t) : sizeof(uoffset_t));
+}
+
+// Helper to see if the identifier in a buffer has the expected value.
+inline bool BufferHasIdentifier(const void *buf, const char *identifier, bool size_prefixed = false)
+{
+ return strncmp(GetBufferIdentifier(buf, size_prefixed), identifier,
+ FlatBufferBuilder::kFileIdentifierLength) == 0;
+}
+
+// Helper class to verify the integrity of a FlatBuffer
+class Verifier FLATBUFFERS_FINAL_CLASS
+{
+public:
+ Verifier(const uint8_t *buf, size_t buf_len, uoffset_t _max_depth = 64,
+ uoffset_t _max_tables = 1000000, bool _check_alignment = true)
+ : buf_(buf), size_(buf_len), depth_(0), max_depth_(_max_depth), num_tables_(0),
+ max_tables_(_max_tables), upper_bound_(0), check_alignment_(_check_alignment)
+ {
+ FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE);
+ }
+
+ // Central location where any verification failures register.
+ bool Check(bool ok) const
+ {
+#ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
+ FLATBUFFERS_ASSERT(ok);
+#endif
+#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
+ if (!ok)
+ upper_bound_ = 0;
+#endif
+ // clang-format on
+ return ok;
+ }
+
+ // Verify any range within the buffer.
+ bool Verify(size_t elem, size_t elem_len) const
+ {
+#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
+ auto upper_bound = elem + elem_len;
+ if (upper_bound_ < upper_bound)
+ upper_bound_ = upper_bound;
+#endif
+ // clang-format on
+ return Check(elem_len < size_ && elem <= size_ - elem_len);
+ }
+
+ template <typename T> bool VerifyAlignment(size_t elem) const
+ {
+ return Check((elem & (sizeof(T) - 1)) == 0 || !check_alignment_);
+ }
+
+ // Verify a range indicated by sizeof(T).
+ template <typename T> bool Verify(size_t elem) const
+ {
+ return VerifyAlignment<T>(elem) && Verify(elem, sizeof(T));
+ }
+
+ bool VerifyFromPointer(const uint8_t *p, size_t len)
+ {
+ auto o = static_cast<size_t>(p - buf_);
+ return Verify(o, len);
+ }
+
+ // Verify relative to a known-good base pointer.
+ bool Verify(const uint8_t *base, voffset_t elem_off, size_t elem_len) const
+ {
+ return Verify(static_cast<size_t>(base - buf_) + elem_off, elem_len);
+ }
+
+ template <typename T> bool Verify(const uint8_t *base, voffset_t elem_off) const
+ {
+ return Verify(static_cast<size_t>(base - buf_) + elem_off, sizeof(T));
+ }
+
+ // Verify a pointer (may be NULL) of a table type.
+ template <typename T> bool VerifyTable(const T *table) { return !table || table->Verify(*this); }
+
+ // Verify a pointer (may be NULL) of any vector type.
+ template <typename T> bool VerifyVector(const Vector<T> *vec) const
+ {
+ return !vec || VerifyVectorOrString(reinterpret_cast<const uint8_t *>(vec), sizeof(T));
+ }
+
+ // Verify a pointer (may be NULL) of a vector to struct.
+ template <typename T> bool VerifyVector(const Vector<const T *> *vec) const
+ {
+ return VerifyVector(reinterpret_cast<const Vector<T> *>(vec));
+ }
+
+ // Verify a pointer (may be NULL) to string.
+ bool VerifyString(const String *str) const
+ {
+ size_t end;
+ return !str || (VerifyVectorOrString(reinterpret_cast<const uint8_t *>(str), 1, &end) &&
+ Verify(end, 1) && // Must have terminator
+ Check(buf_[end] == '\0')); // Terminating byte must be 0.
+ }
+
+ // Common code between vectors and strings.
+ bool VerifyVectorOrString(const uint8_t *vec, size_t elem_size, size_t *end = nullptr) const
+ {
+ auto veco = static_cast<size_t>(vec - buf_);
+ // Check we can read the size field.
+ if (!Verify<uoffset_t>(veco))
+ return false;
+ // Check the whole array. If this is a string, the byte past the array
+ // must be 0.
+ auto size = ReadScalar<uoffset_t>(vec);
+ auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size;
+ if (!Check(size < max_elems))
+ return false; // Protect against byte_size overflowing.
+ auto byte_size = sizeof(size) + elem_size * size;
+ if (end)
+ *end = veco + byte_size;
+ return Verify(veco, byte_size);
+ }
+
+ // Special case for string contents, after the above has been called.
+ bool VerifyVectorOfStrings(const Vector<Offset<String>> *vec) const
+ {
+ if (vec)
+ {
+ for (uoffset_t i = 0; i < vec->size(); i++)
+ {
+ if (!VerifyString(vec->Get(i)))
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // Special case for table contents, after the above has been called.
+ template <typename T> bool VerifyVectorOfTables(const Vector<Offset<T>> *vec)
+ {
+ if (vec)
+ {
+ for (uoffset_t i = 0; i < vec->size(); i++)
+ {
+ if (!vec->Get(i)->Verify(*this))
+ return false;
+ }
+ }
+ return true;
+ }
+
+ __supress_ubsan__("unsigned-integer-overflow") bool VerifyTableStart(const uint8_t *table)
+ {
+ // Check the vtable offset.
+ auto tableo = static_cast<size_t>(table - buf_);
+ if (!Verify<soffset_t>(tableo))
+ return false;
+ // This offset may be signed, but doing the subtraction unsigned always
+ // gives the result we want.
+ auto vtableo = tableo - static_cast<size_t>(ReadScalar<soffset_t>(table));
+ // Check the vtable size field, then check vtable fits in its entirety.
+ return VerifyComplexity() && Verify<voffset_t>(vtableo) &&
+ VerifyAlignment<voffset_t>(ReadScalar<voffset_t>(buf_ + vtableo)) &&
+ Verify(vtableo, ReadScalar<voffset_t>(buf_ + vtableo));
+ }
+
+ template <typename T> bool VerifyBufferFromStart(const char *identifier, size_t start)
+ {
+ if (identifier && !Check((size_ >= 2 * sizeof(flatbuffers::uoffset_t) &&
+ BufferHasIdentifier(buf_ + start, identifier))))
+ {
+ return false;
+ }
+
+ // Call T::Verify, which must be in the generated code for this type.
+ auto o = VerifyOffset(start);
+ return o && reinterpret_cast<const T *>(buf_ + start + o)->Verify(*this)
+#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
+ && GetComputedSize()
+#endif
+ ;
+ // clang-format on
+ }
+
+ // Verify this whole buffer, starting with root type T.
+ template <typename T> bool VerifyBuffer() { return VerifyBuffer<T>(nullptr); }
+
+ template <typename T> bool VerifyBuffer(const char *identifier)
+ {
+ return VerifyBufferFromStart<T>(identifier, 0);
+ }
+
+ template <typename T> bool VerifySizePrefixedBuffer(const char *identifier)
+ {
+ return Verify<uoffset_t>(0U) && ReadScalar<uoffset_t>(buf_) == size_ - sizeof(uoffset_t) &&
+ VerifyBufferFromStart<T>(identifier, sizeof(uoffset_t));
+ }
+
+ uoffset_t VerifyOffset(size_t start) const
+ {
+ if (!Verify<uoffset_t>(start))
+ return 0;
+ auto o = ReadScalar<uoffset_t>(buf_ + start);
+ // May not point to itself.
+ if (!Check(o != 0))
+ return 0;
+ // Can't wrap around / buffers are max 2GB.
+ if (!Check(static_cast<soffset_t>(o) >= 0))
+ return 0;
+ // Must be inside the buffer to create a pointer from it (pointer outside
+ // buffer is UB).
+ if (!Verify(start + o, 1))
+ return 0;
+ return o;
+ }
+
+ uoffset_t VerifyOffset(const uint8_t *base, voffset_t start) const
+ {
+ return VerifyOffset(static_cast<size_t>(base - buf_) + start);
+ }
+
+ // Called at the start of a table to increase counters measuring data
+ // structure depth and amount, and possibly bails out with false if
+ // limits set by the constructor have been hit. Needs to be balanced
+ // with EndTable().
+ bool VerifyComplexity()
+ {
+ depth_++;
+ num_tables_++;
+ return Check(depth_ <= max_depth_ && num_tables_ <= max_tables_);
+ }
+
+ // Called at the end of a table to pop the depth count.
+ bool EndTable()
+ {
+ depth_--;
+ return true;
+ }
+
+ // Returns the message size in bytes
+ size_t GetComputedSize() const
+ {
+#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
+ uintptr_t size = upper_bound_;
+ // Align the size to uoffset_t
+ size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1);
+ return (size > size_) ? 0 : size;
+#else
+ // Must turn on FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE for this to work.
+ (void)upper_bound_;
+ FLATBUFFERS_ASSERT(false);
+ return 0;
+#endif
+ // clang-format on
+ }
+
+private:
+ const uint8_t *buf_;
+ size_t size_;
+ uoffset_t depth_;
+ uoffset_t max_depth_;
+ uoffset_t num_tables_;
+ uoffset_t max_tables_;
+ mutable size_t upper_bound_;
+ bool check_alignment_;
+};
+
+// Convenient way to bundle a buffer and its length, to pass it around
+// typed by its root.
+// A BufferRef does not own its buffer.
+struct BufferRefBase
+{
+}; // for std::is_base_of
+template <typename T> struct BufferRef : BufferRefBase
+{
+ BufferRef() : buf(nullptr), len(0), must_free(false) {}
+ BufferRef(uint8_t *_buf, uoffset_t _len) : buf(_buf), len(_len), must_free(false) {}
+
+ ~BufferRef()
+ {
+ if (must_free)
+ free(buf);
+ }
+
+ const T *GetRoot() const { return flatbuffers::GetRoot<T>(buf); }
+
+ bool Verify()
+ {
+ Verifier verifier(buf, len);
+ return verifier.VerifyBuffer<T>(nullptr);
+ }
+
+ uint8_t *buf;
+ uoffset_t len;
+ bool must_free;
+};
+
+// "structs" are flat structures that do not have an offset table, thus
+// always have all members present and do not support forwards/backwards
+// compatible extensions.
+
+class Struct FLATBUFFERS_FINAL_CLASS
+{
+public:
+ template <typename T> T GetField(uoffset_t o) const { return ReadScalar<T>(&data_[o]); }
+
+ template <typename T> T GetStruct(uoffset_t o) const { return reinterpret_cast<T>(&data_[o]); }
+
+ const uint8_t *GetAddressOf(uoffset_t o) const { return &data_[o]; }
+ uint8_t *GetAddressOf(uoffset_t o) { return &data_[o]; }
+
+private:
+ // private constructor & copy constructor: you obtain instances of this
+ // class by pointing to existing data only
+ Struct();
+ Struct(const Struct &);
+ Struct &operator=(const Struct &);
+
+ uint8_t data_[1];
+};
+
+// "tables" use an offset table (possibly shared) that allows fields to be
+// omitted and added at will, but uses an extra indirection to read.
+class Table
+{
+public:
+ const uint8_t *GetVTable() const { return data_ - ReadScalar<soffset_t>(data_); }
+
+ // This gets the field offset for any of the functions below it, or 0
+ // if the field was not present.
+ voffset_t GetOptionalFieldOffset(voffset_t field) const
+ {
+ // The vtable offset is always at the start.
+ auto vtable = GetVTable();
+ // The first element is the size of the vtable (fields + type id + itself).
+ auto vtsize = ReadScalar<voffset_t>(vtable);
+ // If the field we're accessing is outside the vtable, we're reading older
+ // data, so it's the same as if the offset was 0 (not present).
+ return field < vtsize ? ReadScalar<voffset_t>(vtable + field) : 0;
+ }
+
+ template <typename T> T GetField(voffset_t field, T defaultval) const
+ {
+ auto field_offset = GetOptionalFieldOffset(field);
+ return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval;
+ }
+
+ template <typename P> P GetPointer(voffset_t field)
+ {
+ auto field_offset = GetOptionalFieldOffset(field);
+ auto p = data_ + field_offset;
+ return field_offset ? reinterpret_cast<P>(p + ReadScalar<uoffset_t>(p)) : nullptr;
+ }
+ template <typename P> P GetPointer(voffset_t field) const
+ {
+ return const_cast<Table *>(this)->GetPointer<P>(field);
+ }
+
+ template <typename P> P GetStruct(voffset_t field) const
+ {
+ auto field_offset = GetOptionalFieldOffset(field);
+ auto p = const_cast<uint8_t *>(data_ + field_offset);
+ return field_offset ? reinterpret_cast<P>(p) : nullptr;
+ }
+
+ template <typename Raw, typename Face>
+ flatbuffers::Optional<Face> GetOptional(voffset_t field) const
+ {
+ auto field_offset = GetOptionalFieldOffset(field);
+ auto p = data_ + field_offset;
+ return field_offset ? Optional<Face>(static_cast<Face>(ReadScalar<Raw>(p))) : Optional<Face>();
+ }
+
+ template <typename T> bool SetField(voffset_t field, T val, T def)
+ {
+ auto field_offset = GetOptionalFieldOffset(field);
+ if (!field_offset)
+ return IsTheSameAs(val, def);
+ WriteScalar(data_ + field_offset, val);
+ return true;
+ }
+ template <typename T> bool SetField(voffset_t field, T val)
+ {
+ auto field_offset = GetOptionalFieldOffset(field);
+ if (!field_offset)
+ return false;
+ WriteScalar(data_ + field_offset, val);
+ return true;
+ }
+
+ bool SetPointer(voffset_t field, const uint8_t *val)
+ {
+ auto field_offset = GetOptionalFieldOffset(field);
+ if (!field_offset)
+ return false;
+ WriteScalar(data_ + field_offset, static_cast<uoffset_t>(val - (data_ + field_offset)));
+ return true;
+ }
+
+ uint8_t *GetAddressOf(voffset_t field)
+ {
+ auto field_offset = GetOptionalFieldOffset(field);
+ return field_offset ? data_ + field_offset : nullptr;
+ }
+ const uint8_t *GetAddressOf(voffset_t field) const
+ {
+ return const_cast<Table *>(this)->GetAddressOf(field);
+ }
+
+ bool CheckField(voffset_t field) const { return GetOptionalFieldOffset(field) != 0; }
+
+ // Verify the vtable of this table.
+ // Call this once per table, followed by VerifyField once per field.
+ bool VerifyTableStart(Verifier &verifier) const { return verifier.VerifyTableStart(data_); }
+
+ // Verify a particular field.
+ template <typename T> bool VerifyField(const Verifier &verifier, voffset_t field) const
+ {
+ // Calling GetOptionalFieldOffset should be safe now thanks to
+ // VerifyTable().
+ auto field_offset = GetOptionalFieldOffset(field);
+ // Check the actual field.
+ return !field_offset || verifier.Verify<T>(data_, field_offset);
+ }
+
+ // VerifyField for required fields.
+ template <typename T> bool VerifyFieldRequired(const Verifier &verifier, voffset_t field) const
+ {
+ auto field_offset = GetOptionalFieldOffset(field);
+ return verifier.Check(field_offset != 0) && verifier.Verify<T>(data_, field_offset);
+ }
+
+ // Versions for offsets.
+ bool VerifyOffset(const Verifier &verifier, voffset_t field) const
+ {
+ auto field_offset = GetOptionalFieldOffset(field);
+ return !field_offset || verifier.VerifyOffset(data_, field_offset);
+ }
+
+ bool VerifyOffsetRequired(const Verifier &verifier, voffset_t field) const
+ {
+ auto field_offset = GetOptionalFieldOffset(field);
+ return verifier.Check(field_offset != 0) && verifier.VerifyOffset(data_, field_offset);
+ }
+
+private:
+ // private constructor & copy constructor: you obtain instances of this
+ // class by pointing to existing data only
+ Table();
+ Table(const Table &other);
+ Table &operator=(const Table &);
+
+ uint8_t data_[1];
+};
+
+// This specialization allows avoiding warnings like:
+// MSVC C4800: type: forcing value to bool 'true' or 'false'.
+template <>
+inline flatbuffers::Optional<bool> Table::GetOptional<uint8_t, bool>(voffset_t field) const
+{
+ auto field_offset = GetOptionalFieldOffset(field);
+ auto p = data_ + field_offset;
+ return field_offset ? Optional<bool>(ReadScalar<uint8_t>(p) != 0) : Optional<bool>();
+}
+
+template <typename T> void FlatBufferBuilder::Required(Offset<T> table, voffset_t field)
+{
+ auto table_ptr = reinterpret_cast<const Table *>(buf_.data_at(table.o));
+ bool ok = table_ptr->GetOptionalFieldOffset(field) != 0;
+ // If this fails, the caller will show what field needs to be set.
+ FLATBUFFERS_ASSERT(ok);
+ (void)ok;
+}
+
+/// @brief This can compute the start of a FlatBuffer from a root pointer, i.e.
+/// it is the opposite transformation of GetRoot().
+/// This may be useful if you want to pass on a root and have the recipient
+/// delete the buffer afterwards.
+inline const uint8_t *GetBufferStartFromRootPointer(const void *root)
+{
+ auto table = reinterpret_cast<const Table *>(root);
+ auto vtable = table->GetVTable();
+ // Either the vtable is before the root or after the root.
+ auto start = (std::min)(vtable, reinterpret_cast<const uint8_t *>(root));
+ // Align to at least sizeof(uoffset_t).
+ start = reinterpret_cast<const uint8_t *>(reinterpret_cast<uintptr_t>(start) &
+ ~(sizeof(uoffset_t) - 1));
+ // Additionally, there may be a file_identifier in the buffer, and the root
+ // offset. The buffer may have been aligned to any size between
+ // sizeof(uoffset_t) and FLATBUFFERS_MAX_ALIGNMENT (see "force_align").
+ // Sadly, the exact alignment is only known when constructing the buffer,
+ // since it depends on the presence of values with said alignment properties.
+ // So instead, we simply look at the next uoffset_t values (root,
+ // file_identifier, and alignment padding) to see which points to the root.
+ // None of the other values can "impersonate" the root since they will either
+ // be 0 or four ASCII characters.
+ static_assert(FlatBufferBuilder::kFileIdentifierLength == sizeof(uoffset_t),
+ "file_identifier is assumed to be the same size as uoffset_t");
+ for (auto possible_roots = FLATBUFFERS_MAX_ALIGNMENT / sizeof(uoffset_t) + 1; possible_roots;
+ possible_roots--)
+ {
+ start -= sizeof(uoffset_t);
+ if (ReadScalar<uoffset_t>(start) + start == reinterpret_cast<const uint8_t *>(root))
+ return start;
+ }
+ // We didn't find the root, either the "root" passed isn't really a root,
+ // or the buffer is corrupt.
+ // Assert, because calling this function with bad data may cause reads
+ // outside of buffer boundaries.
+ FLATBUFFERS_ASSERT(false);
+ return nullptr;
+}
+
+/// @brief This return the prefixed size of a FlatBuffer.
+inline uoffset_t GetPrefixedSize(const uint8_t *buf) { return ReadScalar<uoffset_t>(buf); }
+
+// Base class for native objects (FlatBuffer data de-serialized into native
+// C++ data structures).
+// Contains no functionality, purely documentative.
+struct NativeTable
+{
+};
+
+/// @brief Function types to be used with resolving hashes into objects and
+/// back again. The resolver gets a pointer to a field inside an object API
+/// object that is of the type specified in the schema using the attribute
+/// `cpp_type` (it is thus important whatever you write to this address
+/// matches that type). The value of this field is initially null, so you
+/// may choose to implement a delayed binding lookup using this function
+/// if you wish. The resolver does the opposite lookup, for when the object
+/// is being serialized again.
+typedef uint64_t hash_value_t;
+// clang-format off
+#ifdef FLATBUFFERS_CPP98_STL
+ typedef void (*resolver_function_t)(void **pointer_adr, hash_value_t hash);
+ typedef hash_value_t (*rehasher_function_t)(void *pointer);
+#else
+ typedef std::function<void (void **pointer_adr, hash_value_t hash)>
+ resolver_function_t;
+ typedef std::function<hash_value_t (void *pointer)> rehasher_function_t;
+#endif
+// clang-format on
+
+// Helper function to test if a field is present, using any of the field
+// enums in the generated code.
+// `table` must be a generated table type. Since this is a template parameter,
+// this is not typechecked to be a subclass of Table, so beware!
+// Note: this function will return false for fields equal to the default
+// value, since they're not stored in the buffer (unless force_defaults was
+// used).
+template <typename T> bool IsFieldPresent(const T *table, typename T::FlatBuffersVTableOffset field)
+{
+ // Cast, since Table is a private baseclass of any table types.
+ return reinterpret_cast<const Table *>(table)->CheckField(static_cast<voffset_t>(field));
+}
+
+// Utility function for reverse lookups on the EnumNames*() functions
+// (in the generated C++ code)
+// names must be NULL terminated.
+inline int LookupEnum(const char **names, const char *name)
+{
+ for (const char **p = names; *p; p++)
+ if (!strcmp(*p, name))
+ return static_cast<int>(p - names);
+ return -1;
+}
+
+// These macros allow us to layout a struct with a guarantee that they'll end
+// up looking the same on different compilers and platforms.
+// It does this by disallowing the compiler to do any padding, and then
+// does padding itself by inserting extra padding fields that make every
+// element aligned to its own size.
+// Additionally, it manually sets the alignment of the struct as a whole,
+// which is typically its largest element, or a custom size set in the schema
+// by the force_align attribute.
+// These are used in the generated code only.
+
+// clang-format off
+#if defined(_MSC_VER)
+ #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
+ __pragma(pack(1)) \
+ struct __declspec(align(alignment))
+ #define FLATBUFFERS_STRUCT_END(name, size) \
+ __pragma(pack()) \
+ static_assert(sizeof(name) == size, "compiler breaks packing rules")
+#elif defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__)
+ #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
+ _Pragma("pack(1)") \
+ struct __attribute__((aligned(alignment)))
+ #define FLATBUFFERS_STRUCT_END(name, size) \
+ _Pragma("pack()") \
+ static_assert(sizeof(name) == size, "compiler breaks packing rules")
+#else
+ #error Unknown compiler, please define structure alignment macros
+#endif
+// clang-format on
+
+// Minimal reflection via code generation.
+// Besides full-fat reflection (see reflection.h) and parsing/printing by
+// loading schemas (see idl.h), we can also have code generation for mimimal
+// reflection data which allows pretty-printing and other uses without needing
+// a schema or a parser.
+// Generate code with --reflect-types (types only) or --reflect-names (names
+// also) to enable.
+// See minireflect.h for utilities using this functionality.
+
+// These types are organized slightly differently as the ones in idl.h.
+enum SequenceType
+{
+ ST_TABLE,
+ ST_STRUCT,
+ ST_UNION,
+ ST_ENUM
+};
+
+// Scalars have the same order as in idl.h
+// clang-format off
+#define FLATBUFFERS_GEN_ELEMENTARY_TYPES(ET) \
+ ET(ET_UTYPE) \
+ ET(ET_BOOL) \
+ ET(ET_CHAR) \
+ ET(ET_UCHAR) \
+ ET(ET_SHORT) \
+ ET(ET_USHORT) \
+ ET(ET_INT) \
+ ET(ET_UINT) \
+ ET(ET_LONG) \
+ ET(ET_ULONG) \
+ ET(ET_FLOAT) \
+ ET(ET_DOUBLE) \
+ ET(ET_STRING) \
+ ET(ET_SEQUENCE) // See SequenceType.
+
+enum ElementaryType {
+ #define FLATBUFFERS_ET(E) E,
+ FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET)
+ #undef FLATBUFFERS_ET
+};
+
+inline const char * const *ElementaryTypeNames() {
+ static const char * const names[] = {
+ #define FLATBUFFERS_ET(E) #E,
+ FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET)
+ #undef FLATBUFFERS_ET
+ };
+ return names;
+}
+// clang-format on
+
+// Basic type info cost just 16bits per field!
+// We're explicitly defining the signedness since the signedness of integer
+// bitfields is otherwise implementation-defined and causes warnings on older
+// GCC compilers.
+struct TypeCode
+{
+ // ElementaryType
+ unsigned short base_type : 4;
+ // Either vector (in table) or array (in struct)
+ unsigned short is_repeating : 1;
+ // Index into type_refs below, or -1 for none.
+ signed short sequence_ref : 11;
+};
+
+static_assert(sizeof(TypeCode) == 2, "TypeCode");
+
+struct TypeTable;
+
+// Signature of the static method present in each type.
+typedef const TypeTable *(*TypeFunction)();
+
+struct TypeTable
+{
+ SequenceType st;
+ size_t num_elems; // of type_codes, values, names (but not type_refs).
+ const TypeCode *type_codes; // num_elems count
+ const TypeFunction *type_refs; // less than num_elems entries (see TypeCode).
+ const int16_t *array_sizes; // less than num_elems entries (see TypeCode).
+ const int64_t *values; // Only set for non-consecutive enum/union or structs.
+ const char *const *names; // Only set if compiled with --reflect-names.
+};
+
+// String which identifies the current version of FlatBuffers.
+// flatbuffer_version_string is used by Google developers to identify which
+// applications uploaded to Google Play are using this library. This allows
+// the development team at Google to determine the popularity of the library.
+// How it works: Applications that are uploaded to the Google Play Store are
+// scanned for this version string. We track which applications are using it
+// to measure popularity. You are free to remove it (of course) but we would
+// appreciate if you left it in.
+
+// Weak linkage is culled by VS & doesn't work on cygwin.
+// clang-format off
+#if !defined(_WIN32) && !defined(__CYGWIN__)
+
+extern volatile __attribute__((weak)) const char *flatbuffer_version_string;
+volatile __attribute__((weak)) const char *flatbuffer_version_string =
+ "FlatBuffers "
+ FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "."
+ FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "."
+ FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
+
+#endif // !defined(_WIN32) && !defined(__CYGWIN__)
+
+#define FLATBUFFERS_DEFINE_BITMASK_OPERATORS(E, T)\
+ inline E operator | (E lhs, E rhs){\
+ return E(T(lhs) | T(rhs));\
+ }\
+ inline E operator & (E lhs, E rhs){\
+ return E(T(lhs) & T(rhs));\
+ }\
+ inline E operator ^ (E lhs, E rhs){\
+ return E(T(lhs) ^ T(rhs));\
+ }\
+ inline E operator ~ (E lhs){\
+ return E(~T(lhs));\
+ }\
+ inline E operator |= (E &lhs, E rhs){\
+ lhs = lhs | rhs;\
+ return lhs;\
+ }\
+ inline E operator &= (E &lhs, E rhs){\
+ lhs = lhs & rhs;\
+ return lhs;\
+ }\
+ inline E operator ^= (E &lhs, E rhs){\
+ lhs = lhs ^ rhs;\
+ return lhs;\
+ }\
+ inline bool operator !(E rhs) \
+ {\
+ return !bool(T(rhs)); \
+ }
+/// @endcond
+} // namespace flatbuffers
+
+// clang-format on
+
+#endif // FLATBUFFERS_H_
diff --git a/onert-micro/externals/flatbuffers/flatc.h b/onert-micro/externals/flatbuffers/flatc.h
new file mode 100644
index 000000000..594bf792a
--- /dev/null
+++ b/onert-micro/externals/flatbuffers/flatc.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2017 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLATBUFFERS_FLATC_H_
+#define FLATBUFFERS_FLATC_H_
+
+#include <functional>
+#include <limits>
+#include <string>
+
+#include "flatbuffers/flatbuffers.h"
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+
+namespace flatbuffers
+{
+
+extern void LogCompilerWarn(const std::string &warn);
+extern void LogCompilerError(const std::string &err);
+
+class FlatCompiler
+{
+public:
+ // Output generator for the various programming languages and formats we
+ // support.
+ struct Generator
+ {
+ typedef bool (*GenerateFn)(const flatbuffers::Parser &parser, const std::string &path,
+ const std::string &file_name);
+ typedef std::string (*MakeRuleFn)(const flatbuffers::Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+ GenerateFn generate;
+ const char *generator_opt_short;
+ const char *generator_opt_long;
+ const char *lang_name;
+ bool schema_only;
+ GenerateFn generateGRPC;
+ flatbuffers::IDLOptions::Language lang;
+ const char *generator_help;
+ MakeRuleFn make_rule;
+ };
+
+ typedef void (*WarnFn)(const FlatCompiler *flatc, const std::string &warn, bool show_exe_name);
+
+ typedef void (*ErrorFn)(const FlatCompiler *flatc, const std::string &err, bool usage,
+ bool show_exe_name);
+
+ // Parameters required to initialize the FlatCompiler.
+ struct InitParams
+ {
+ InitParams() : generators(nullptr), num_generators(0), warn_fn(nullptr), error_fn(nullptr) {}
+
+ const Generator *generators;
+ size_t num_generators;
+ WarnFn warn_fn;
+ ErrorFn error_fn;
+ };
+
+ explicit FlatCompiler(const InitParams &params) : params_(params) {}
+
+ int Compile(int argc, const char **argv);
+
+ std::string GetUsageString(const char *program_name) const;
+
+private:
+ void ParseFile(flatbuffers::Parser &parser, const std::string &filename,
+ const std::string &contents, std::vector<const char *> &include_directories) const;
+
+ void LoadBinarySchema(Parser &parser, const std::string &filename, const std::string &contents);
+
+ void Warn(const std::string &warn, bool show_exe_name = true) const;
+
+ void Error(const std::string &err, bool usage = true, bool show_exe_name = true) const;
+
+ InitParams params_;
+};
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_FLATC_H_
diff --git a/onert-micro/externals/flatbuffers/flexbuffers.h b/onert-micro/externals/flatbuffers/flexbuffers.h
new file mode 100644
index 000000000..f6fcbf34b
--- /dev/null
+++ b/onert-micro/externals/flatbuffers/flexbuffers.h
@@ -0,0 +1,1852 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2017 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLATBUFFERS_FLEXBUFFERS_H_
+#define FLATBUFFERS_FLEXBUFFERS_H_
+
+#include <map>
+// Used to select STL variant.
+#include "flatbuffers/base.h"
+// We use the basic binary writing functions from the regular FlatBuffers.
+#include "flatbuffers/util.h"
+
+#ifdef _MSC_VER
+#include <intrin.h>
+#endif
+
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4127) // C4127: conditional expression is constant
+#endif
+
+namespace flexbuffers
+{
+
+class Reference;
+class Map;
+
+// These are used in the lower 2 bits of a type field to determine the size of
+// the elements (and or size field) of the item pointed to (e.g. vector).
+enum BitWidth
+{
+ BIT_WIDTH_8 = 0,
+ BIT_WIDTH_16 = 1,
+ BIT_WIDTH_32 = 2,
+ BIT_WIDTH_64 = 3,
+};
+
+// These are used as the upper 6 bits of a type field to indicate the actual
+// type.
+enum Type
+{
+ FBT_NULL = 0,
+ FBT_INT = 1,
+ FBT_UINT = 2,
+ FBT_FLOAT = 3,
+ // Types above stored inline, types below store an offset.
+ FBT_KEY = 4,
+ FBT_STRING = 5,
+ FBT_INDIRECT_INT = 6,
+ FBT_INDIRECT_UINT = 7,
+ FBT_INDIRECT_FLOAT = 8,
+ FBT_MAP = 9,
+ FBT_VECTOR = 10, // Untyped.
+ FBT_VECTOR_INT = 11, // Typed any size (stores no type table).
+ FBT_VECTOR_UINT = 12,
+ FBT_VECTOR_FLOAT = 13,
+ FBT_VECTOR_KEY = 14,
+ // DEPRECATED, use FBT_VECTOR or FBT_VECTOR_KEY instead.
+ // Read test.cpp/FlexBuffersDeprecatedTest() for details on why.
+ FBT_VECTOR_STRING_DEPRECATED = 15,
+ FBT_VECTOR_INT2 = 16, // Typed tuple (no type table, no size field).
+ FBT_VECTOR_UINT2 = 17,
+ FBT_VECTOR_FLOAT2 = 18,
+ FBT_VECTOR_INT3 = 19, // Typed triple (no type table, no size field).
+ FBT_VECTOR_UINT3 = 20,
+ FBT_VECTOR_FLOAT3 = 21,
+ FBT_VECTOR_INT4 = 22, // Typed quad (no type table, no size field).
+ FBT_VECTOR_UINT4 = 23,
+ FBT_VECTOR_FLOAT4 = 24,
+ FBT_BLOB = 25,
+ FBT_BOOL = 26,
+ FBT_VECTOR_BOOL = 36, // To Allow the same type of conversion of type to vector type
+};
+
+inline bool IsInline(Type t) { return t <= FBT_FLOAT || t == FBT_BOOL; }
+
+inline bool IsTypedVectorElementType(Type t)
+{
+ return (t >= FBT_INT && t <= FBT_STRING) || t == FBT_BOOL;
+}
+
+inline bool IsTypedVector(Type t)
+{
+ return (t >= FBT_VECTOR_INT && t <= FBT_VECTOR_STRING_DEPRECATED) || t == FBT_VECTOR_BOOL;
+}
+
+inline bool IsFixedTypedVector(Type t) { return t >= FBT_VECTOR_INT2 && t <= FBT_VECTOR_FLOAT4; }
+
+inline Type ToTypedVector(Type t, size_t fixed_len = 0)
+{
+ FLATBUFFERS_ASSERT(IsTypedVectorElementType(t));
+ switch (fixed_len)
+ {
+ case 0:
+ return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT);
+ case 2:
+ return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT2);
+ case 3:
+ return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT3);
+ case 4:
+ return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT4);
+ default:
+ FLATBUFFERS_ASSERT(0);
+ return FBT_NULL;
+ }
+}
+
+inline Type ToTypedVectorElementType(Type t)
+{
+ FLATBUFFERS_ASSERT(IsTypedVector(t));
+ return static_cast<Type>(t - FBT_VECTOR_INT + FBT_INT);
+}
+
+inline Type ToFixedTypedVectorElementType(Type t, uint8_t *len)
+{
+ FLATBUFFERS_ASSERT(IsFixedTypedVector(t));
+ auto fixed_type = t - FBT_VECTOR_INT2;
+ *len = static_cast<uint8_t>(fixed_type / 3 + 2); // 3 types each, starting from length 2.
+ return static_cast<Type>(fixed_type % 3 + FBT_INT);
+}
+
+// TODO: implement proper support for 8/16bit floats, or decide not to
+// support them.
+typedef int16_t half;
+typedef int8_t quarter;
+
+// TODO: can we do this without conditionals using intrinsics or inline asm
+// on some platforms? Given branch prediction the method below should be
+// decently quick, but it is the most frequently executed function.
+// We could do an (unaligned) 64-bit read if we ifdef out the platforms for
+// which that doesn't work (or where we'd read into un-owned memory).
+template <typename R, typename T1, typename T2, typename T4, typename T8>
+R ReadSizedScalar(const uint8_t *data, uint8_t byte_width)
+{
+ return byte_width < 4 ? (byte_width < 2 ? static_cast<R>(flatbuffers::ReadScalar<T1>(data))
+ : static_cast<R>(flatbuffers::ReadScalar<T2>(data)))
+ : (byte_width < 8 ? static_cast<R>(flatbuffers::ReadScalar<T4>(data))
+ : static_cast<R>(flatbuffers::ReadScalar<T8>(data)));
+}
+
+inline int64_t ReadInt64(const uint8_t *data, uint8_t byte_width)
+{
+ return ReadSizedScalar<int64_t, int8_t, int16_t, int32_t, int64_t>(data, byte_width);
+}
+
+inline uint64_t ReadUInt64(const uint8_t *data, uint8_t byte_width)
+{
+#if defined(_MSC_VER) && ((defined(_M_X64) && !defined(_M_ARM64EC)) || defined _M_IX86)
+ uint64_t u = 0;
+ __movsb(reinterpret_cast<uint8_t *>(&u), reinterpret_cast<const uint8_t *>(data), byte_width);
+ return flatbuffers::EndianScalar(u);
+#else
+ return ReadSizedScalar<uint64_t, uint8_t, uint16_t, uint32_t, uint64_t>(data, byte_width);
+#endif
+ // clang-format on
+}
+
+inline double ReadDouble(const uint8_t *data, uint8_t byte_width)
+{
+ return ReadSizedScalar<double, quarter, half, float, double>(data, byte_width);
+}
+
+inline const uint8_t *Indirect(const uint8_t *offset, uint8_t byte_width)
+{
+ return offset - ReadUInt64(offset, byte_width);
+}
+
+template <typename T> const uint8_t *Indirect(const uint8_t *offset)
+{
+ return offset - flatbuffers::ReadScalar<T>(offset);
+}
+
+inline BitWidth WidthU(uint64_t u)
+{
+#define FLATBUFFERS_GET_FIELD_BIT_WIDTH(value, width) \
+ { \
+ if (!((u) & ~((1ULL << (width)) - 1ULL))) \
+ return BIT_WIDTH_##width; \
+ }
+ FLATBUFFERS_GET_FIELD_BIT_WIDTH(u, 8);
+ FLATBUFFERS_GET_FIELD_BIT_WIDTH(u, 16);
+ FLATBUFFERS_GET_FIELD_BIT_WIDTH(u, 32);
+#undef FLATBUFFERS_GET_FIELD_BIT_WIDTH
+ return BIT_WIDTH_64;
+}
+
+inline BitWidth WidthI(int64_t i)
+{
+ auto u = static_cast<uint64_t>(i) << 1;
+ return WidthU(i >= 0 ? u : ~u);
+}
+
+inline BitWidth WidthF(double f)
+{
+ return static_cast<double>(static_cast<float>(f)) == f ? BIT_WIDTH_32 : BIT_WIDTH_64;
+}
+
+// Base class of all types below.
+// Points into the data buffer and allows access to one type.
+class Object
+{
+public:
+ Object(const uint8_t *data, uint8_t byte_width) : data_(data), byte_width_(byte_width) {}
+
+protected:
+ const uint8_t *data_;
+ uint8_t byte_width_;
+};
+
+// Object that has a size, obtained either from size prefix, or elsewhere.
+class Sized : public Object
+{
+public:
+ // Size prefix.
+ Sized(const uint8_t *data, uint8_t byte_width) : Object(data, byte_width), size_(read_size()) {}
+ // Manual size.
+ Sized(const uint8_t *data, uint8_t byte_width, size_t sz) : Object(data, byte_width), size_(sz) {}
+ size_t size() const { return size_; }
+ // Access size stored in `byte_width_` bytes before data_ pointer.
+ size_t read_size() const
+ {
+ return static_cast<size_t>(ReadUInt64(data_ - byte_width_, byte_width_));
+ }
+
+protected:
+ size_t size_;
+};
+
+class String : public Sized
+{
+public:
+ // Size prefix.
+ String(const uint8_t *data, uint8_t byte_width) : Sized(data, byte_width) {}
+ // Manual size.
+ String(const uint8_t *data, uint8_t byte_width, size_t sz) : Sized(data, byte_width, sz) {}
+
+ size_t length() const { return size(); }
+ const char *c_str() const { return reinterpret_cast<const char *>(data_); }
+ std::string str() const { return std::string(c_str(), size()); }
+
+ static String EmptyString()
+ {
+ static const char *empty_string = "";
+ return String(reinterpret_cast<const uint8_t *>(empty_string), 1, 0);
+ }
+ bool IsTheEmptyString() const { return data_ == EmptyString().data_; }
+};
+
+class Blob : public Sized
+{
+public:
+ Blob(const uint8_t *data_buf, uint8_t byte_width) : Sized(data_buf, byte_width) {}
+
+ static Blob EmptyBlob()
+ {
+ static const uint8_t empty_blob[] = {0 /*len*/};
+ return Blob(empty_blob + 1, 1);
+ }
+ bool IsTheEmptyBlob() const { return data_ == EmptyBlob().data_; }
+ const uint8_t *data() const { return data_; }
+};
+
+class Vector : public Sized
+{
+public:
+ Vector(const uint8_t *data, uint8_t byte_width) : Sized(data, byte_width) {}
+
+ Reference operator[](size_t i) const;
+
+ static Vector EmptyVector()
+ {
+ static const uint8_t empty_vector[] = {0 /*len*/};
+ return Vector(empty_vector + 1, 1);
+ }
+ bool IsTheEmptyVector() const { return data_ == EmptyVector().data_; }
+};
+
+class TypedVector : public Sized
+{
+public:
+ TypedVector(const uint8_t *data, uint8_t byte_width, Type element_type)
+ : Sized(data, byte_width), type_(element_type)
+ {
+ }
+
+ Reference operator[](size_t i) const;
+
+ static TypedVector EmptyTypedVector()
+ {
+ static const uint8_t empty_typed_vector[] = {0 /*len*/};
+ return TypedVector(empty_typed_vector + 1, 1, FBT_INT);
+ }
+ bool IsTheEmptyVector() const { return data_ == TypedVector::EmptyTypedVector().data_; }
+
+ Type ElementType() { return type_; }
+
+ friend Reference;
+
+private:
+ Type type_;
+
+ friend Map;
+};
+
+class FixedTypedVector : public Object
+{
+public:
+ FixedTypedVector(const uint8_t *data, uint8_t byte_width, Type element_type, uint8_t len)
+ : Object(data, byte_width), type_(element_type), len_(len)
+ {
+ }
+
+ Reference operator[](size_t i) const;
+
+ static FixedTypedVector EmptyFixedTypedVector()
+ {
+ static const uint8_t fixed_empty_vector[] = {0 /* unused */};
+ return FixedTypedVector(fixed_empty_vector, 1, FBT_INT, 0);
+ }
+ bool IsTheEmptyFixedTypedVector() const
+ {
+ return data_ == FixedTypedVector::EmptyFixedTypedVector().data_;
+ }
+
+ Type ElementType() { return type_; }
+ uint8_t size() { return len_; }
+
+private:
+ Type type_;
+ uint8_t len_;
+};
+
+class Map : public Vector
+{
+public:
+ Map(const uint8_t *data, uint8_t byte_width) : Vector(data, byte_width) {}
+
+ Reference operator[](const char *key) const;
+ Reference operator[](const std::string &key) const;
+
+ Vector Values() const { return Vector(data_, byte_width_); }
+
+ TypedVector Keys() const
+ {
+ const size_t num_prefixed_fields = 3;
+ auto keys_offset = data_ - byte_width_ * num_prefixed_fields;
+ return TypedVector(Indirect(keys_offset, byte_width_),
+ static_cast<uint8_t>(ReadUInt64(keys_offset + byte_width_, byte_width_)),
+ FBT_KEY);
+ }
+
+ static Map EmptyMap()
+ {
+ static const uint8_t empty_map[] = {
+ 0 /*keys_len*/, 0 /*keys_offset*/, 1 /*keys_width*/, 0 /*len*/
+ };
+ return Map(empty_map + 4, 1);
+ }
+
+ bool IsTheEmptyMap() const { return data_ == EmptyMap().data_; }
+};
+
+template <typename T> void AppendToString(std::string &s, T &&v, bool keys_quoted)
+{
+ s += "[ ";
+ for (size_t i = 0; i < v.size(); i++)
+ {
+ if (i)
+ s += ", ";
+ v[i].ToString(true, keys_quoted, s);
+ }
+ s += " ]";
+}
+
+class Reference
+{
+public:
+ Reference() : data_(nullptr), parent_width_(0), byte_width_(BIT_WIDTH_8), type_(FBT_NULL) {}
+
+ Reference(const uint8_t *data, uint8_t parent_width, uint8_t byte_width, Type type)
+ : data_(data), parent_width_(parent_width), byte_width_(byte_width), type_(type)
+ {
+ }
+
+ Reference(const uint8_t *data, uint8_t parent_width, uint8_t packed_type)
+ : data_(data), parent_width_(parent_width)
+ {
+ byte_width_ = 1U << static_cast<BitWidth>(packed_type & 3);
+ type_ = static_cast<Type>(packed_type >> 2);
+ }
+
+ Type GetType() const { return type_; }
+
+ bool IsNull() const { return type_ == FBT_NULL; }
+ bool IsBool() const { return type_ == FBT_BOOL; }
+ bool IsInt() const { return type_ == FBT_INT || type_ == FBT_INDIRECT_INT; }
+ bool IsUInt() const { return type_ == FBT_UINT || type_ == FBT_INDIRECT_UINT; }
+ bool IsIntOrUint() const { return IsInt() || IsUInt(); }
+ bool IsFloat() const { return type_ == FBT_FLOAT || type_ == FBT_INDIRECT_FLOAT; }
+ bool IsNumeric() const { return IsIntOrUint() || IsFloat(); }
+ bool IsString() const { return type_ == FBT_STRING; }
+ bool IsKey() const { return type_ == FBT_KEY; }
+ bool IsVector() const { return type_ == FBT_VECTOR || type_ == FBT_MAP; }
+ bool IsUntypedVector() const { return type_ == FBT_VECTOR; }
+ bool IsTypedVector() const { return flexbuffers::IsTypedVector(type_); }
+ bool IsFixedTypedVector() const { return flexbuffers::IsFixedTypedVector(type_); }
+ bool IsAnyVector() const { return (IsTypedVector() || IsFixedTypedVector() || IsVector()); }
+ bool IsMap() const { return type_ == FBT_MAP; }
+ bool IsBlob() const { return type_ == FBT_BLOB; }
+ bool AsBool() const
+ {
+ return (type_ == FBT_BOOL ? ReadUInt64(data_, parent_width_) : AsUInt64()) != 0;
+ }
+
+ // Reads any type as a int64_t. Never fails, does most sensible conversion.
+ // Truncates floats, strings are attempted to be parsed for a number,
+ // vectors/maps return their size. Returns 0 if all else fails.
+ int64_t AsInt64() const
+ {
+ if (type_ == FBT_INT)
+ {
+ // A fast path for the common case.
+ return ReadInt64(data_, parent_width_);
+ }
+ else
+ switch (type_)
+ {
+ case FBT_INDIRECT_INT:
+ return ReadInt64(Indirect(), byte_width_);
+ case FBT_UINT:
+ return ReadUInt64(data_, parent_width_);
+ case FBT_INDIRECT_UINT:
+ return ReadUInt64(Indirect(), byte_width_);
+ case FBT_FLOAT:
+ return static_cast<int64_t>(ReadDouble(data_, parent_width_));
+ case FBT_INDIRECT_FLOAT:
+ return static_cast<int64_t>(ReadDouble(Indirect(), byte_width_));
+ case FBT_NULL:
+ return 0;
+ case FBT_STRING:
+ return flatbuffers::StringToInt(AsString().c_str());
+ case FBT_VECTOR:
+ return static_cast<int64_t>(AsVector().size());
+ case FBT_BOOL:
+ return ReadInt64(data_, parent_width_);
+ default:
+ // Convert other things to int.
+ return 0;
+ }
+ }
+
+ // TODO: could specialize these to not use AsInt64() if that saves
+ // extension ops in generated code, and use a faster op than ReadInt64.
+ int32_t AsInt32() const { return static_cast<int32_t>(AsInt64()); }
+ int16_t AsInt16() const { return static_cast<int16_t>(AsInt64()); }
+ int8_t AsInt8() const { return static_cast<int8_t>(AsInt64()); }
+
+ uint64_t AsUInt64() const
+ {
+ if (type_ == FBT_UINT)
+ {
+ // A fast path for the common case.
+ return ReadUInt64(data_, parent_width_);
+ }
+ else
+ switch (type_)
+ {
+ case FBT_INDIRECT_UINT:
+ return ReadUInt64(Indirect(), byte_width_);
+ case FBT_INT:
+ return ReadInt64(data_, parent_width_);
+ case FBT_INDIRECT_INT:
+ return ReadInt64(Indirect(), byte_width_);
+ case FBT_FLOAT:
+ return static_cast<uint64_t>(ReadDouble(data_, parent_width_));
+ case FBT_INDIRECT_FLOAT:
+ return static_cast<uint64_t>(ReadDouble(Indirect(), byte_width_));
+ case FBT_NULL:
+ return 0;
+ case FBT_STRING:
+ return flatbuffers::StringToUInt(AsString().c_str());
+ case FBT_VECTOR:
+ return static_cast<uint64_t>(AsVector().size());
+ case FBT_BOOL:
+ return ReadUInt64(data_, parent_width_);
+ default:
+ // Convert other things to uint.
+ return 0;
+ }
+ }
+
+ uint32_t AsUInt32() const { return static_cast<uint32_t>(AsUInt64()); }
+ uint16_t AsUInt16() const { return static_cast<uint16_t>(AsUInt64()); }
+ uint8_t AsUInt8() const { return static_cast<uint8_t>(AsUInt64()); }
+
+ double AsDouble() const
+ {
+ if (type_ == FBT_FLOAT)
+ {
+ // A fast path for the common case.
+ return ReadDouble(data_, parent_width_);
+ }
+ else
+ switch (type_)
+ {
+ case FBT_INDIRECT_FLOAT:
+ return ReadDouble(Indirect(), byte_width_);
+ case FBT_INT:
+ return static_cast<double>(ReadInt64(data_, parent_width_));
+ case FBT_UINT:
+ return static_cast<double>(ReadUInt64(data_, parent_width_));
+ case FBT_INDIRECT_INT:
+ return static_cast<double>(ReadInt64(Indirect(), byte_width_));
+ case FBT_INDIRECT_UINT:
+ return static_cast<double>(ReadUInt64(Indirect(), byte_width_));
+ case FBT_NULL:
+ return 0.0;
+ case FBT_STRING:
+ {
+ double d;
+ flatbuffers::StringToNumber(AsString().c_str(), &d);
+ return d;
+ }
+ case FBT_VECTOR:
+ return static_cast<double>(AsVector().size());
+ case FBT_BOOL:
+ return static_cast<double>(ReadUInt64(data_, parent_width_));
+ default:
+ // Convert strings and other things to float.
+ return 0;
+ }
+ }
+
+ float AsFloat() const { return static_cast<float>(AsDouble()); }
+
+ const char *AsKey() const
+ {
+ if (type_ == FBT_KEY || type_ == FBT_STRING)
+ {
+ return reinterpret_cast<const char *>(Indirect());
+ }
+ else
+ {
+ return "";
+ }
+ }
+
+ // This function returns the empty string if you try to read something that
+ // is not a string or key.
+ String AsString() const
+ {
+ if (type_ == FBT_STRING)
+ {
+ return String(Indirect(), byte_width_);
+ }
+ else if (type_ == FBT_KEY)
+ {
+ auto key = Indirect();
+ return String(key, byte_width_, strlen(reinterpret_cast<const char *>(key)));
+ }
+ else
+ {
+ return String::EmptyString();
+ }
+ }
+
+ // Unlike AsString(), this will convert any type to a std::string.
+ std::string ToString() const
+ {
+ std::string s;
+ ToString(false, false, s);
+ return s;
+ }
+
+ // Convert any type to a JSON-like string. strings_quoted determines if
+ // string values at the top level receive "" quotes (inside other values
+ // they always do). keys_quoted determines if keys are quoted, at any level.
+ // TODO(wvo): add further options to have indentation/newlines.
+ void ToString(bool strings_quoted, bool keys_quoted, std::string &s) const
+ {
+ if (type_ == FBT_STRING)
+ {
+ String str(Indirect(), byte_width_);
+ if (strings_quoted)
+ {
+ flatbuffers::EscapeString(str.c_str(), str.length(), &s, true, false);
+ }
+ else
+ {
+ s.append(str.c_str(), str.length());
+ }
+ }
+ else if (IsKey())
+ {
+ auto str = AsKey();
+ if (keys_quoted)
+ {
+ flatbuffers::EscapeString(str, strlen(str), &s, true, false);
+ }
+ else
+ {
+ s += str;
+ }
+ }
+ else if (IsInt())
+ {
+ s += flatbuffers::NumToString(AsInt64());
+ }
+ else if (IsUInt())
+ {
+ s += flatbuffers::NumToString(AsUInt64());
+ }
+ else if (IsFloat())
+ {
+ s += flatbuffers::NumToString(AsDouble());
+ }
+ else if (IsNull())
+ {
+ s += "null";
+ }
+ else if (IsBool())
+ {
+ s += AsBool() ? "true" : "false";
+ }
+ else if (IsMap())
+ {
+ s += "{ ";
+ auto m = AsMap();
+ auto keys = m.Keys();
+ auto vals = m.Values();
+ for (size_t i = 0; i < keys.size(); i++)
+ {
+ keys[i].ToString(true, keys_quoted, s);
+ s += ": ";
+ vals[i].ToString(true, keys_quoted, s);
+ if (i < keys.size() - 1)
+ s += ", ";
+ }
+ s += " }";
+ }
+ else if (IsVector())
+ {
+ AppendToString<Vector>(s, AsVector(), keys_quoted);
+ }
+ else if (IsTypedVector())
+ {
+ AppendToString<TypedVector>(s, AsTypedVector(), keys_quoted);
+ }
+ else if (IsFixedTypedVector())
+ {
+ AppendToString<FixedTypedVector>(s, AsFixedTypedVector(), keys_quoted);
+ }
+ else if (IsBlob())
+ {
+ auto blob = AsBlob();
+ flatbuffers::EscapeString(reinterpret_cast<const char *>(blob.data()), blob.size(), &s, true,
+ false);
+ }
+ else
+ {
+ s += "(?)";
+ }
+ }
+
+ // This function returns the empty blob if you try to read a not-blob.
+ // Strings can be viewed as blobs too.
+ Blob AsBlob() const
+ {
+ if (type_ == FBT_BLOB || type_ == FBT_STRING)
+ {
+ return Blob(Indirect(), byte_width_);
+ }
+ else
+ {
+ return Blob::EmptyBlob();
+ }
+ }
+
+ // This function returns the empty vector if you try to read a not-vector.
+ // Maps can be viewed as vectors too.
+ Vector AsVector() const
+ {
+ if (type_ == FBT_VECTOR || type_ == FBT_MAP)
+ {
+ return Vector(Indirect(), byte_width_);
+ }
+ else
+ {
+ return Vector::EmptyVector();
+ }
+ }
+
+ TypedVector AsTypedVector() const
+ {
+ if (IsTypedVector())
+ {
+ auto tv = TypedVector(Indirect(), byte_width_, ToTypedVectorElementType(type_));
+ if (tv.type_ == FBT_STRING)
+ {
+ // These can't be accessed as strings, since we don't know the bit-width
+ // of the size field, see the declaration of
+ // FBT_VECTOR_STRING_DEPRECATED above for details.
+ // We change the type here to be keys, which are a subtype of strings,
+ // and will ignore the size field. This will truncate strings with
+ // embedded nulls.
+ tv.type_ = FBT_KEY;
+ }
+ return tv;
+ }
+ else
+ {
+ return TypedVector::EmptyTypedVector();
+ }
+ }
+
+ FixedTypedVector AsFixedTypedVector() const
+ {
+ if (IsFixedTypedVector())
+ {
+ uint8_t len = 0;
+ auto vtype = ToFixedTypedVectorElementType(type_, &len);
+ return FixedTypedVector(Indirect(), byte_width_, vtype, len);
+ }
+ else
+ {
+ return FixedTypedVector::EmptyFixedTypedVector();
+ }
+ }
+
+ Map AsMap() const
+ {
+ if (type_ == FBT_MAP)
+ {
+ return Map(Indirect(), byte_width_);
+ }
+ else
+ {
+ return Map::EmptyMap();
+ }
+ }
+
+ template <typename T> T As() const;
+
+ // Experimental: Mutation functions.
+ // These allow scalars in an already created buffer to be updated in-place.
+ // Since by default scalars are stored in the smallest possible space,
+ // the new value may not fit, in which case these functions return false.
+ // To avoid this, you can construct the values you intend to mutate using
+ // Builder::ForceMinimumBitWidth.
+ bool MutateInt(int64_t i)
+ {
+ if (type_ == FBT_INT)
+ {
+ return Mutate(data_, i, parent_width_, WidthI(i));
+ }
+ else if (type_ == FBT_INDIRECT_INT)
+ {
+ return Mutate(Indirect(), i, byte_width_, WidthI(i));
+ }
+ else if (type_ == FBT_UINT)
+ {
+ auto u = static_cast<uint64_t>(i);
+ return Mutate(data_, u, parent_width_, WidthU(u));
+ }
+ else if (type_ == FBT_INDIRECT_UINT)
+ {
+ auto u = static_cast<uint64_t>(i);
+ return Mutate(Indirect(), u, byte_width_, WidthU(u));
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ bool MutateBool(bool b)
+ {
+ return type_ == FBT_BOOL && Mutate(data_, b, parent_width_, BIT_WIDTH_8);
+ }
+
+ bool MutateUInt(uint64_t u)
+ {
+ if (type_ == FBT_UINT)
+ {
+ return Mutate(data_, u, parent_width_, WidthU(u));
+ }
+ else if (type_ == FBT_INDIRECT_UINT)
+ {
+ return Mutate(Indirect(), u, byte_width_, WidthU(u));
+ }
+ else if (type_ == FBT_INT)
+ {
+ auto i = static_cast<int64_t>(u);
+ return Mutate(data_, i, parent_width_, WidthI(i));
+ }
+ else if (type_ == FBT_INDIRECT_INT)
+ {
+ auto i = static_cast<int64_t>(u);
+ return Mutate(Indirect(), i, byte_width_, WidthI(i));
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ bool MutateFloat(float f)
+ {
+ if (type_ == FBT_FLOAT)
+ {
+ return MutateF(data_, f, parent_width_, BIT_WIDTH_32);
+ }
+ else if (type_ == FBT_INDIRECT_FLOAT)
+ {
+ return MutateF(Indirect(), f, byte_width_, BIT_WIDTH_32);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ bool MutateFloat(double d)
+ {
+ if (type_ == FBT_FLOAT)
+ {
+ return MutateF(data_, d, parent_width_, WidthF(d));
+ }
+ else if (type_ == FBT_INDIRECT_FLOAT)
+ {
+ return MutateF(Indirect(), d, byte_width_, WidthF(d));
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ bool MutateString(const char *str, size_t len)
+ {
+ auto s = AsString();
+ if (s.IsTheEmptyString())
+ return false;
+ // This is very strict, could allow shorter strings, but that creates
+ // garbage.
+ if (s.length() != len)
+ return false;
+ memcpy(const_cast<char *>(s.c_str()), str, len);
+ return true;
+ }
+ bool MutateString(const char *str) { return MutateString(str, strlen(str)); }
+ bool MutateString(const std::string &str) { return MutateString(str.data(), str.length()); }
+
+private:
+ const uint8_t *Indirect() const { return flexbuffers::Indirect(data_, parent_width_); }
+
+ template <typename T>
+ bool Mutate(const uint8_t *dest, T t, size_t byte_width, BitWidth value_width)
+ {
+ auto fits = static_cast<size_t>(static_cast<size_t>(1U) << value_width) <= byte_width;
+ if (fits)
+ {
+ t = flatbuffers::EndianScalar(t);
+ memcpy(const_cast<uint8_t *>(dest), &t, byte_width);
+ }
+ return fits;
+ }
+
+ template <typename T>
+ bool MutateF(const uint8_t *dest, T t, size_t byte_width, BitWidth value_width)
+ {
+ if (byte_width == sizeof(double))
+ return Mutate(dest, static_cast<double>(t), byte_width, value_width);
+ if (byte_width == sizeof(float))
+ return Mutate(dest, static_cast<float>(t), byte_width, value_width);
+ FLATBUFFERS_ASSERT(false);
+ return false;
+ }
+
+ const uint8_t *data_;
+ uint8_t parent_width_;
+ uint8_t byte_width_;
+ Type type_;
+};
+
+// Template specialization for As().
+template <> inline bool Reference::As<bool>() const { return AsBool(); }
+
+template <> inline int8_t Reference::As<int8_t>() const { return AsInt8(); }
+template <> inline int16_t Reference::As<int16_t>() const { return AsInt16(); }
+template <> inline int32_t Reference::As<int32_t>() const { return AsInt32(); }
+template <> inline int64_t Reference::As<int64_t>() const { return AsInt64(); }
+
+template <> inline uint8_t Reference::As<uint8_t>() const { return AsUInt8(); }
+template <> inline uint16_t Reference::As<uint16_t>() const { return AsUInt16(); }
+template <> inline uint32_t Reference::As<uint32_t>() const { return AsUInt32(); }
+template <> inline uint64_t Reference::As<uint64_t>() const { return AsUInt64(); }
+
+template <> inline double Reference::As<double>() const { return AsDouble(); }
+template <> inline float Reference::As<float>() const { return AsFloat(); }
+
+template <> inline String Reference::As<String>() const { return AsString(); }
+template <> inline std::string Reference::As<std::string>() const { return AsString().str(); }
+
+template <> inline Blob Reference::As<Blob>() const { return AsBlob(); }
+template <> inline Vector Reference::As<Vector>() const { return AsVector(); }
+template <> inline TypedVector Reference::As<TypedVector>() const { return AsTypedVector(); }
+template <> inline FixedTypedVector Reference::As<FixedTypedVector>() const
+{
+ return AsFixedTypedVector();
+}
+template <> inline Map Reference::As<Map>() const { return AsMap(); }
+
+inline uint8_t PackedType(BitWidth bit_width, Type type)
+{
+ return static_cast<uint8_t>(bit_width | (type << 2));
+}
+
+inline uint8_t NullPackedType() { return PackedType(BIT_WIDTH_8, FBT_NULL); }
+
+// Vector accessors.
+// Note: if you try to access outside of bounds, you get a Null value back
+// instead. Normally this would be an assert, but since this is "dynamically
+// typed" data, you may not want that (someone sends you a 2d vector and you
+// wanted 3d).
+// The Null converts seamlessly into a default value for any other type.
+// TODO(wvo): Could introduce an #ifdef that makes this into an assert?
+inline Reference Vector::operator[](size_t i) const
+{
+ auto len = size();
+ if (i >= len)
+ return Reference(nullptr, 1, NullPackedType());
+ auto packed_type = (data_ + len * byte_width_)[i];
+ auto elem = data_ + i * byte_width_;
+ return Reference(elem, byte_width_, packed_type);
+}
+
+inline Reference TypedVector::operator[](size_t i) const
+{
+ auto len = size();
+ if (i >= len)
+ return Reference(nullptr, 1, NullPackedType());
+ auto elem = data_ + i * byte_width_;
+ return Reference(elem, byte_width_, 1, type_);
+}
+
+inline Reference FixedTypedVector::operator[](size_t i) const
+{
+ if (i >= len_)
+ return Reference(nullptr, 1, NullPackedType());
+ auto elem = data_ + i * byte_width_;
+ return Reference(elem, byte_width_, 1, type_);
+}
+
+template <typename T> int KeyCompare(const void *key, const void *elem)
+{
+ auto str_elem =
+ reinterpret_cast<const char *>(Indirect<T>(reinterpret_cast<const uint8_t *>(elem)));
+ auto skey = reinterpret_cast<const char *>(key);
+ return strcmp(skey, str_elem);
+}
+
+inline Reference Map::operator[](const char *key) const
+{
+ auto keys = Keys();
+ // We can't pass keys.byte_width_ to the comparison function, so we have
+ // to pick the right one ahead of time.
+ int (*comp)(const void *, const void *) = nullptr;
+ switch (keys.byte_width_)
+ {
+ case 1:
+ comp = KeyCompare<uint8_t>;
+ break;
+ case 2:
+ comp = KeyCompare<uint16_t>;
+ break;
+ case 4:
+ comp = KeyCompare<uint32_t>;
+ break;
+ case 8:
+ comp = KeyCompare<uint64_t>;
+ break;
+ }
+ auto res = std::bsearch(key, keys.data_, keys.size(), keys.byte_width_, comp);
+ if (!res)
+ return Reference(nullptr, 1, NullPackedType());
+ auto i = (reinterpret_cast<uint8_t *>(res) - keys.data_) / keys.byte_width_;
+ return (*static_cast<const Vector *>(this))[i];
+}
+
+inline Reference Map::operator[](const std::string &key) const { return (*this)[key.c_str()]; }
+
+inline Reference GetRoot(const uint8_t *buffer, size_t size)
+{
+ // See Finish() below for the serialization counterpart of this.
+ // The root starts at the end of the buffer, so we parse backwards from there.
+ auto end = buffer + size;
+ auto byte_width = *--end;
+ auto packed_type = *--end;
+ end -= byte_width; // The root data item.
+ return Reference(end, byte_width, packed_type);
+}
+
+inline Reference GetRoot(const std::vector<uint8_t> &buffer)
+{
+ return GetRoot(flatbuffers::vector_data(buffer), buffer.size());
+}
+
+// Flags that configure how the Builder behaves.
+// The "Share" flags determine if the Builder automatically tries to pool
+// this type. Pooling can reduce the size of serialized data if there are
+// multiple maps of the same kind, at the expense of slightly slower
+// serialization (the cost of lookups) and more memory use (std::set).
+// By default this is on for keys, but off for strings.
+// Turn keys off if you have e.g. only one map.
+// Turn strings on if you expect many non-unique string values.
+// Additionally, sharing key vectors can save space if you have maps with
+// identical field populations.
+enum BuilderFlag
+{
+ BUILDER_FLAG_NONE = 0,
+ BUILDER_FLAG_SHARE_KEYS = 1,
+ BUILDER_FLAG_SHARE_STRINGS = 2,
+ BUILDER_FLAG_SHARE_KEYS_AND_STRINGS = 3,
+ BUILDER_FLAG_SHARE_KEY_VECTORS = 4,
+ BUILDER_FLAG_SHARE_ALL = 7,
+};
+
+class Builder FLATBUFFERS_FINAL_CLASS
+{
+public:
+ Builder(size_t initial_size = 256, BuilderFlag flags = BUILDER_FLAG_SHARE_KEYS)
+ : buf_(initial_size), finished_(false), has_duplicate_keys_(false), flags_(flags),
+ force_min_bit_width_(BIT_WIDTH_8), key_pool(KeyOffsetCompare(buf_)),
+ string_pool(StringOffsetCompare(buf_))
+ {
+ buf_.clear();
+ }
+
+#ifdef FLATBUFFERS_DEFAULT_DECLARATION
+ Builder(Builder &&) = default;
+ Builder &operator=(Builder &&) = default;
+#endif
+
+ /// @brief Get the serialized buffer (after you call `Finish()`).
+ /// @return Returns a vector owned by this class.
+ const std::vector<uint8_t> &GetBuffer() const
+ {
+ Finished();
+ return buf_;
+ }
+
+ // Size of the buffer. Does not include unfinished values.
+ size_t GetSize() const { return buf_.size(); }
+
+ // Reset all state so we can re-use the buffer.
+ void Clear()
+ {
+ buf_.clear();
+ stack_.clear();
+ finished_ = false;
+ // flags_ remains as-is;
+ force_min_bit_width_ = BIT_WIDTH_8;
+ key_pool.clear();
+ string_pool.clear();
+ }
+
+ // All value constructing functions below have two versions: one that
+ // takes a key (for placement inside a map) and one that doesn't (for inside
+ // vectors and elsewhere).
+
+ void Null() { stack_.push_back(Value()); }
+ void Null(const char *key)
+ {
+ Key(key);
+ Null();
+ }
+
+ void Int(int64_t i) { stack_.push_back(Value(i, FBT_INT, WidthI(i))); }
+ void Int(const char *key, int64_t i)
+ {
+ Key(key);
+ Int(i);
+ }
+
+ void UInt(uint64_t u) { stack_.push_back(Value(u, FBT_UINT, WidthU(u))); }
+ void UInt(const char *key, uint64_t u)
+ {
+ Key(key);
+ UInt(u);
+ }
+
+ void Float(float f) { stack_.push_back(Value(f)); }
+ void Float(const char *key, float f)
+ {
+ Key(key);
+ Float(f);
+ }
+
+ void Double(double f) { stack_.push_back(Value(f)); }
+ void Double(const char *key, double d)
+ {
+ Key(key);
+ Double(d);
+ }
+
+ void Bool(bool b) { stack_.push_back(Value(b)); }
+ void Bool(const char *key, bool b)
+ {
+ Key(key);
+ Bool(b);
+ }
+
+ void IndirectInt(int64_t i) { PushIndirect(i, FBT_INDIRECT_INT, WidthI(i)); }
+ void IndirectInt(const char *key, int64_t i)
+ {
+ Key(key);
+ IndirectInt(i);
+ }
+
+ void IndirectUInt(uint64_t u) { PushIndirect(u, FBT_INDIRECT_UINT, WidthU(u)); }
+ void IndirectUInt(const char *key, uint64_t u)
+ {
+ Key(key);
+ IndirectUInt(u);
+ }
+
+ void IndirectFloat(float f) { PushIndirect(f, FBT_INDIRECT_FLOAT, BIT_WIDTH_32); }
+ void IndirectFloat(const char *key, float f)
+ {
+ Key(key);
+ IndirectFloat(f);
+ }
+
+ void IndirectDouble(double f) { PushIndirect(f, FBT_INDIRECT_FLOAT, WidthF(f)); }
+ void IndirectDouble(const char *key, double d)
+ {
+ Key(key);
+ IndirectDouble(d);
+ }
+
+ size_t Key(const char *str, size_t len)
+ {
+ auto sloc = buf_.size();
+ WriteBytes(str, len + 1);
+ if (flags_ & BUILDER_FLAG_SHARE_KEYS)
+ {
+ auto it = key_pool.find(sloc);
+ if (it != key_pool.end())
+ {
+ // Already in the buffer. Remove key we just serialized, and use
+ // existing offset instead.
+ buf_.resize(sloc);
+ sloc = *it;
+ }
+ else
+ {
+ key_pool.insert(sloc);
+ }
+ }
+ stack_.push_back(Value(static_cast<uint64_t>(sloc), FBT_KEY, BIT_WIDTH_8));
+ return sloc;
+ }
+
+ size_t Key(const char *str) { return Key(str, strlen(str)); }
+ size_t Key(const std::string &str) { return Key(str.c_str(), str.size()); }
+
+ size_t String(const char *str, size_t len)
+ {
+ auto reset_to = buf_.size();
+ auto sloc = CreateBlob(str, len, 1, FBT_STRING);
+ if (flags_ & BUILDER_FLAG_SHARE_STRINGS)
+ {
+ StringOffset so(sloc, len);
+ auto it = string_pool.find(so);
+ if (it != string_pool.end())
+ {
+ // Already in the buffer. Remove string we just serialized, and use
+ // existing offset instead.
+ buf_.resize(reset_to);
+ sloc = it->first;
+ stack_.back().u_ = sloc;
+ }
+ else
+ {
+ string_pool.insert(so);
+ }
+ }
+ return sloc;
+ }
+ size_t String(const char *str) { return String(str, strlen(str)); }
+ size_t String(const std::string &str) { return String(str.c_str(), str.size()); }
+ void String(const flexbuffers::String &str) { String(str.c_str(), str.length()); }
+
+ void String(const char *key, const char *str)
+ {
+ Key(key);
+ String(str);
+ }
+ void String(const char *key, const std::string &str)
+ {
+ Key(key);
+ String(str);
+ }
+ void String(const char *key, const flexbuffers::String &str)
+ {
+ Key(key);
+ String(str);
+ }
+
+ size_t Blob(const void *data, size_t len) { return CreateBlob(data, len, 0, FBT_BLOB); }
+ size_t Blob(const std::vector<uint8_t> &v)
+ {
+ return CreateBlob(flatbuffers::vector_data(v), v.size(), 0, FBT_BLOB);
+ }
+
+ // TODO(wvo): support all the FlexBuffer types (like flexbuffers::String),
+ // e.g. Vector etc. Also in overloaded versions.
+ // Also some FlatBuffers types?
+
+ size_t StartVector() { return stack_.size(); }
+ size_t StartVector(const char *key)
+ {
+ Key(key);
+ return stack_.size();
+ }
+ size_t StartMap() { return stack_.size(); }
+ size_t StartMap(const char *key)
+ {
+ Key(key);
+ return stack_.size();
+ }
+
+ // TODO(wvo): allow this to specify an aligment greater than the natural
+ // alignment.
+ size_t EndVector(size_t start, bool typed, bool fixed)
+ {
+ auto vec = CreateVector(start, stack_.size() - start, 1, typed, fixed);
+ // Remove temp elements and return vector.
+ stack_.resize(start);
+ stack_.push_back(vec);
+ return static_cast<size_t>(vec.u_);
+ }
+
+ size_t EndMap(size_t start)
+ {
+ // We should have interleaved keys and values on the stack.
+ // Make sure it is an even number:
+ auto len = stack_.size() - start;
+ FLATBUFFERS_ASSERT(!(len & 1));
+ len /= 2;
+ // Make sure keys are all strings:
+ for (auto key = start; key < stack_.size(); key += 2)
+ {
+ FLATBUFFERS_ASSERT(stack_[key].type_ == FBT_KEY);
+ }
+ // Now sort values, so later we can do a binary search lookup.
+ // We want to sort 2 array elements at a time.
+ struct TwoValue
+ {
+ Value key;
+ Value val;
+ };
+ // TODO(wvo): strict aliasing?
+ // TODO(wvo): allow the caller to indicate the data is already sorted
+ // for maximum efficiency? With an assert to check sortedness to make sure
+ // we're not breaking binary search.
+ // Or, we can track if the map is sorted as keys are added which would be
+ // be quite cheap (cheaper than checking it here), so we can skip this
+ // step automatically when appliccable, and encourage people to write in
+ // sorted fashion.
+ // std::sort is typically already a lot faster on sorted data though.
+ auto dict = reinterpret_cast<TwoValue *>(flatbuffers::vector_data(stack_) + start);
+ std::sort(dict, dict + len, [&](const TwoValue &a, const TwoValue &b) -> bool {
+ auto as = reinterpret_cast<const char *>(flatbuffers::vector_data(buf_) + a.key.u_);
+ auto bs = reinterpret_cast<const char *>(flatbuffers::vector_data(buf_) + b.key.u_);
+ auto comp = strcmp(as, bs);
+ // We want to disallow duplicate keys, since this results in a
+ // map where values cannot be found.
+ // But we can't assert here (since we don't want to fail on
+ // random JSON input) or have an error mechanism.
+ // Instead, we set has_duplicate_keys_ in the builder to
+ // signal this.
+ // TODO: Have to check for pointer equality, as some sort
+ // implementation apparently call this function with the same
+ // element?? Why?
+ if (!comp && &a != &b)
+ has_duplicate_keys_ = true;
+ return comp < 0;
+ });
+ // First create a vector out of all keys.
+ // TODO(wvo): if kBuilderFlagShareKeyVectors is true, see if we can share
+ // the first vector.
+ auto keys = CreateVector(start, len, 2, true, false);
+ auto vec = CreateVector(start + 1, len, 2, false, false, &keys);
+ // Remove temp elements and return map.
+ stack_.resize(start);
+ stack_.push_back(vec);
+ return static_cast<size_t>(vec.u_);
+ }
+
+ // Call this after EndMap to see if the map had any duplicate keys.
+ // Any map with such keys won't be able to retrieve all values.
+ bool HasDuplicateKeys() const { return has_duplicate_keys_; }
+
+ template <typename F> size_t Vector(F f)
+ {
+ auto start = StartVector();
+ f();
+ return EndVector(start, false, false);
+ }
+ template <typename F, typename T> size_t Vector(F f, T &state)
+ {
+ auto start = StartVector();
+ f(state);
+ return EndVector(start, false, false);
+ }
+ template <typename F> size_t Vector(const char *key, F f)
+ {
+ auto start = StartVector(key);
+ f();
+ return EndVector(start, false, false);
+ }
+ template <typename F, typename T> size_t Vector(const char *key, F f, T &state)
+ {
+ auto start = StartVector(key);
+ f(state);
+ return EndVector(start, false, false);
+ }
+
+ template <typename T> void Vector(const T *elems, size_t len)
+ {
+ if (flatbuffers::is_scalar<T>::value)
+ {
+ // This path should be a lot quicker and use less space.
+ ScalarVector(elems, len, false);
+ }
+ else
+ {
+ auto start = StartVector();
+ for (size_t i = 0; i < len; i++)
+ Add(elems[i]);
+ EndVector(start, false, false);
+ }
+ }
+ template <typename T> void Vector(const char *key, const T *elems, size_t len)
+ {
+ Key(key);
+ Vector(elems, len);
+ }
+ template <typename T> void Vector(const std::vector<T> &vec)
+ {
+ Vector(flatbuffers::vector_data(vec), vec.size());
+ }
+
+ template <typename F> size_t TypedVector(F f)
+ {
+ auto start = StartVector();
+ f();
+ return EndVector(start, true, false);
+ }
+ template <typename F, typename T> size_t TypedVector(F f, T &state)
+ {
+ auto start = StartVector();
+ f(state);
+ return EndVector(start, true, false);
+ }
+ template <typename F> size_t TypedVector(const char *key, F f)
+ {
+ auto start = StartVector(key);
+ f();
+ return EndVector(start, true, false);
+ }
+ template <typename F, typename T> size_t TypedVector(const char *key, F f, T &state)
+ {
+ auto start = StartVector(key);
+ f(state);
+ return EndVector(start, true, false);
+ }
+
+ template <typename T> size_t FixedTypedVector(const T *elems, size_t len)
+ {
+ // We only support a few fixed vector lengths. Anything bigger use a
+ // regular typed vector.
+ FLATBUFFERS_ASSERT(len >= 2 && len <= 4);
+ // And only scalar values.
+ static_assert(flatbuffers::is_scalar<T>::value, "Unrelated types");
+ return ScalarVector(elems, len, true);
+ }
+
+ template <typename T> size_t FixedTypedVector(const char *key, const T *elems, size_t len)
+ {
+ Key(key);
+ return FixedTypedVector(elems, len);
+ }
+
+ template <typename F> size_t Map(F f)
+ {
+ auto start = StartMap();
+ f();
+ return EndMap(start);
+ }
+ template <typename F, typename T> size_t Map(F f, T &state)
+ {
+ auto start = StartMap();
+ f(state);
+ return EndMap(start);
+ }
+ template <typename F> size_t Map(const char *key, F f)
+ {
+ auto start = StartMap(key);
+ f();
+ return EndMap(start);
+ }
+ template <typename F, typename T> size_t Map(const char *key, F f, T &state)
+ {
+ auto start = StartMap(key);
+ f(state);
+ return EndMap(start);
+ }
+ template <typename T> void Map(const std::map<std::string, T> &map)
+ {
+ auto start = StartMap();
+ for (auto it = map.begin(); it != map.end(); ++it)
+ Add(it->first.c_str(), it->second);
+ EndMap(start);
+ }
+
+ // If you wish to share a value explicitly (a value not shared automatically
+ // through one of the BUILDER_FLAG_SHARE_* flags) you can do so with these
+ // functions. Or if you wish to turn those flags off for performance reasons
+ // and still do some explicit sharing. For example:
+ // builder.IndirectDouble(M_PI);
+ // auto id = builder.LastValue(); // Remember where we stored it.
+ // .. more code goes here ..
+ // builder.ReuseValue(id); // Refers to same double by offset.
+ // LastValue works regardless of whether the value has a key or not.
+ // Works on any data type.
+ struct Value;
+ Value LastValue() { return stack_.back(); }
+ void ReuseValue(Value v) { stack_.push_back(v); }
+ void ReuseValue(const char *key, Value v)
+ {
+ Key(key);
+ ReuseValue(v);
+ }
+
+ // Overloaded Add that tries to call the correct function above.
+ void Add(int8_t i) { Int(i); }
+ void Add(int16_t i) { Int(i); }
+ void Add(int32_t i) { Int(i); }
+ void Add(int64_t i) { Int(i); }
+ void Add(uint8_t u) { UInt(u); }
+ void Add(uint16_t u) { UInt(u); }
+ void Add(uint32_t u) { UInt(u); }
+ void Add(uint64_t u) { UInt(u); }
+ void Add(float f) { Float(f); }
+ void Add(double d) { Double(d); }
+ void Add(bool b) { Bool(b); }
+ void Add(const char *str) { String(str); }
+ void Add(const std::string &str) { String(str); }
+ void Add(const flexbuffers::String &str) { String(str); }
+
+ template <typename T> void Add(const std::vector<T> &vec) { Vector(vec); }
+
+ template <typename T> void Add(const char *key, const T &t)
+ {
+ Key(key);
+ Add(t);
+ }
+
+ template <typename T> void Add(const std::map<std::string, T> &map) { Map(map); }
+
+ template <typename T> void operator+=(const T &t) { Add(t); }
+
+ // This function is useful in combination with the Mutate* functions above.
+ // It forces elements of vectors and maps to have a minimum size, such that
+ // they can later be updated without failing.
+ // Call with no arguments to reset.
+ void ForceMinimumBitWidth(BitWidth bw = BIT_WIDTH_8) { force_min_bit_width_ = bw; }
+
+ void Finish()
+ {
+ // If you hit this assert, you likely have objects that were never included
+ // in a parent. You need to have exactly one root to finish a buffer.
+ // Check your Start/End calls are matched, and all objects are inside
+ // some other object.
+ FLATBUFFERS_ASSERT(stack_.size() == 1);
+
+ // Write root value.
+ auto byte_width = Align(stack_[0].ElemWidth(buf_.size(), 0));
+ WriteAny(stack_[0], byte_width);
+ // Write root type.
+ Write(stack_[0].StoredPackedType(), 1);
+ // Write root size. Normally determined by parent, but root has no parent :)
+ Write(byte_width, 1);
+
+ finished_ = true;
+ }
+
+private:
+ void Finished() const
+ {
+ // If you get this assert, you're attempting to get access a buffer
+ // which hasn't been finished yet. Be sure to call
+ // Builder::Finish with your root object.
+ FLATBUFFERS_ASSERT(finished_);
+ }
+
+ // Align to prepare for writing a scalar with a certain size.
+ uint8_t Align(BitWidth alignment)
+ {
+ auto byte_width = 1U << alignment;
+ buf_.insert(buf_.end(), flatbuffers::PaddingBytes(buf_.size(), byte_width), 0);
+ return static_cast<uint8_t>(byte_width);
+ }
+
+ void WriteBytes(const void *val, size_t size)
+ {
+ buf_.insert(buf_.end(), reinterpret_cast<const uint8_t *>(val),
+ reinterpret_cast<const uint8_t *>(val) + size);
+ }
+
+ template <typename T> void Write(T val, size_t byte_width)
+ {
+ FLATBUFFERS_ASSERT(sizeof(T) >= byte_width);
+ val = flatbuffers::EndianScalar(val);
+ WriteBytes(&val, byte_width);
+ }
+
+ void WriteDouble(double f, uint8_t byte_width)
+ {
+ switch (byte_width)
+ {
+ case 8:
+ Write(f, byte_width);
+ break;
+ case 4:
+ Write(static_cast<float>(f), byte_width);
+ break;
+ // case 2: Write(static_cast<half>(f), byte_width); break;
+ // case 1: Write(static_cast<quarter>(f), byte_width); break;
+ default:
+ FLATBUFFERS_ASSERT(0);
+ }
+ }
+
+ void WriteOffset(uint64_t o, uint8_t byte_width)
+ {
+ auto reloff = buf_.size() - o;
+ FLATBUFFERS_ASSERT(byte_width == 8 || reloff < 1ULL << (byte_width * 8));
+ Write(reloff, byte_width);
+ }
+
+ template <typename T> void PushIndirect(T val, Type type, BitWidth bit_width)
+ {
+ auto byte_width = Align(bit_width);
+ auto iloc = buf_.size();
+ Write(val, byte_width);
+ stack_.push_back(Value(static_cast<uint64_t>(iloc), type, bit_width));
+ }
+
+ static BitWidth WidthB(size_t byte_width)
+ {
+ switch (byte_width)
+ {
+ case 1:
+ return BIT_WIDTH_8;
+ case 2:
+ return BIT_WIDTH_16;
+ case 4:
+ return BIT_WIDTH_32;
+ case 8:
+ return BIT_WIDTH_64;
+ default:
+ FLATBUFFERS_ASSERT(false);
+ return BIT_WIDTH_64;
+ }
+ }
+
+ template <typename T> static Type GetScalarType()
+ {
+ static_assert(flatbuffers::is_scalar<T>::value, "Unrelated types");
+ return flatbuffers::is_floating_point<T>::value
+ ? FBT_FLOAT
+ : flatbuffers::is_same<T, bool>::value
+ ? FBT_BOOL
+ : (flatbuffers::is_unsigned<T>::value ? FBT_UINT : FBT_INT);
+ }
+
+public:
+ // This was really intended to be private, except for LastValue/ReuseValue.
+ struct Value
+ {
+ union {
+ int64_t i_;
+ uint64_t u_;
+ double f_;
+ };
+
+ Type type_;
+
+ // For scalars: of itself, for vector: of its elements, for string: length.
+ BitWidth min_bit_width_;
+
+ Value() : i_(0), type_(FBT_NULL), min_bit_width_(BIT_WIDTH_8) {}
+
+ Value(bool b) : u_(static_cast<uint64_t>(b)), type_(FBT_BOOL), min_bit_width_(BIT_WIDTH_8) {}
+
+ Value(int64_t i, Type t, BitWidth bw) : i_(i), type_(t), min_bit_width_(bw) {}
+ Value(uint64_t u, Type t, BitWidth bw) : u_(u), type_(t), min_bit_width_(bw) {}
+
+ Value(float f) : f_(static_cast<double>(f)), type_(FBT_FLOAT), min_bit_width_(BIT_WIDTH_32) {}
+ Value(double f) : f_(f), type_(FBT_FLOAT), min_bit_width_(WidthF(f)) {}
+
+ uint8_t StoredPackedType(BitWidth parent_bit_width_ = BIT_WIDTH_8) const
+ {
+ return PackedType(StoredWidth(parent_bit_width_), type_);
+ }
+
+ BitWidth ElemWidth(size_t buf_size, size_t elem_index) const
+ {
+ if (IsInline(type_))
+ {
+ return min_bit_width_;
+ }
+ else
+ {
+ // We have an absolute offset, but want to store a relative offset
+ // elem_index elements beyond the current buffer end. Since whether
+ // the relative offset fits in a certain byte_width depends on
+ // the size of the elements before it (and their alignment), we have
+ // to test for each size in turn.
+ for (size_t byte_width = 1; byte_width <= sizeof(flatbuffers::largest_scalar_t);
+ byte_width *= 2)
+ {
+ // Where are we going to write this offset?
+ auto offset_loc =
+ buf_size + flatbuffers::PaddingBytes(buf_size, byte_width) + elem_index * byte_width;
+ // Compute relative offset.
+ auto offset = offset_loc - u_;
+ // Does it fit?
+ auto bit_width = WidthU(offset);
+ if (static_cast<size_t>(static_cast<size_t>(1U) << bit_width) == byte_width)
+ return bit_width;
+ }
+ FLATBUFFERS_ASSERT(false); // Must match one of the sizes above.
+ return BIT_WIDTH_64;
+ }
+ }
+
+ BitWidth StoredWidth(BitWidth parent_bit_width_ = BIT_WIDTH_8) const
+ {
+ if (IsInline(type_))
+ {
+ return (std::max)(min_bit_width_, parent_bit_width_);
+ }
+ else
+ {
+ return min_bit_width_;
+ }
+ }
+ };
+
+private:
+ void WriteAny(const Value &val, uint8_t byte_width)
+ {
+ switch (val.type_)
+ {
+ case FBT_NULL:
+ case FBT_INT:
+ Write(val.i_, byte_width);
+ break;
+ case FBT_BOOL:
+ case FBT_UINT:
+ Write(val.u_, byte_width);
+ break;
+ case FBT_FLOAT:
+ WriteDouble(val.f_, byte_width);
+ break;
+ default:
+ WriteOffset(val.u_, byte_width);
+ break;
+ }
+ }
+
+ size_t CreateBlob(const void *data, size_t len, size_t trailing, Type type)
+ {
+ auto bit_width = WidthU(len);
+ auto byte_width = Align(bit_width);
+ Write<uint64_t>(len, byte_width);
+ auto sloc = buf_.size();
+ WriteBytes(data, len + trailing);
+ stack_.push_back(Value(static_cast<uint64_t>(sloc), type, bit_width));
+ return sloc;
+ }
+
+ template <typename T> size_t ScalarVector(const T *elems, size_t len, bool fixed)
+ {
+ auto vector_type = GetScalarType<T>();
+ auto byte_width = sizeof(T);
+ auto bit_width = WidthB(byte_width);
+ // If you get this assert, you're trying to write a vector with a size
+ // field that is bigger than the scalars you're trying to write (e.g. a
+ // byte vector > 255 elements). For such types, write a "blob" instead.
+ // TODO: instead of asserting, could write vector with larger elements
+ // instead, though that would be wasteful.
+ FLATBUFFERS_ASSERT(WidthU(len) <= bit_width);
+ Align(bit_width);
+ if (!fixed)
+ Write<uint64_t>(len, byte_width);
+ auto vloc = buf_.size();
+ for (size_t i = 0; i < len; i++)
+ Write(elems[i], byte_width);
+ stack_.push_back(
+ Value(static_cast<uint64_t>(vloc), ToTypedVector(vector_type, fixed ? len : 0), bit_width));
+ return vloc;
+ }
+
+ Value CreateVector(size_t start, size_t vec_len, size_t step, bool typed, bool fixed,
+ const Value *keys = nullptr)
+ {
+ FLATBUFFERS_ASSERT(!fixed || typed); // typed=false, fixed=true combination is not supported.
+ // Figure out smallest bit width we can store this vector with.
+ auto bit_width = (std::max)(force_min_bit_width_, WidthU(vec_len));
+ auto prefix_elems = 1;
+ if (keys)
+ {
+ // If this vector is part of a map, we will pre-fix an offset to the keys
+ // to this vector.
+ bit_width = (std::max)(bit_width, keys->ElemWidth(buf_.size(), 0));
+ prefix_elems += 2;
+ }
+ Type vector_type = FBT_KEY;
+ // Check bit widths and types for all elements.
+ for (size_t i = start; i < stack_.size(); i += step)
+ {
+ auto elem_width = stack_[i].ElemWidth(buf_.size(), i - start + prefix_elems);
+ bit_width = (std::max)(bit_width, elem_width);
+ if (typed)
+ {
+ if (i == start)
+ {
+ vector_type = stack_[i].type_;
+ }
+ else
+ {
+ // If you get this assert, you are writing a typed vector with
+ // elements that are not all the same type.
+ FLATBUFFERS_ASSERT(vector_type == stack_[i].type_);
+ }
+ }
+ }
+ // If you get this assert, your fixed types are not one of:
+ // Int / UInt / Float / Key.
+ FLATBUFFERS_ASSERT(!fixed || IsTypedVectorElementType(vector_type));
+ auto byte_width = Align(bit_width);
+ // Write vector. First the keys width/offset if available, and size.
+ if (keys)
+ {
+ WriteOffset(keys->u_, byte_width);
+ Write<uint64_t>(1ULL << keys->min_bit_width_, byte_width);
+ }
+ if (!fixed)
+ Write<uint64_t>(vec_len, byte_width);
+ // Then the actual data.
+ auto vloc = buf_.size();
+ for (size_t i = start; i < stack_.size(); i += step)
+ {
+ WriteAny(stack_[i], byte_width);
+ }
+ // Then the types.
+ if (!typed)
+ {
+ for (size_t i = start; i < stack_.size(); i += step)
+ {
+ buf_.push_back(stack_[i].StoredPackedType(bit_width));
+ }
+ }
+ return Value(static_cast<uint64_t>(vloc),
+ keys ? FBT_MAP
+ : (typed ? ToTypedVector(vector_type, fixed ? vec_len : 0) : FBT_VECTOR),
+ bit_width);
+ }
+
+ // You shouldn't really be copying instances of this class.
+ Builder(const Builder &);
+ Builder &operator=(const Builder &);
+
+ std::vector<uint8_t> buf_;
+ std::vector<Value> stack_;
+
+ bool finished_;
+ bool has_duplicate_keys_;
+
+ BuilderFlag flags_;
+
+ BitWidth force_min_bit_width_;
+
+ struct KeyOffsetCompare
+ {
+ explicit KeyOffsetCompare(const std::vector<uint8_t> &buf) : buf_(&buf) {}
+ bool operator()(size_t a, size_t b) const
+ {
+ auto stra = reinterpret_cast<const char *>(flatbuffers::vector_data(*buf_) + a);
+ auto strb = reinterpret_cast<const char *>(flatbuffers::vector_data(*buf_) + b);
+ return strcmp(stra, strb) < 0;
+ }
+ const std::vector<uint8_t> *buf_;
+ };
+
+ typedef std::pair<size_t, size_t> StringOffset;
+ struct StringOffsetCompare
+ {
+ explicit StringOffsetCompare(const std::vector<uint8_t> &buf) : buf_(&buf) {}
+ bool operator()(const StringOffset &a, const StringOffset &b) const
+ {
+ auto stra = reinterpret_cast<const char *>(flatbuffers::vector_data(*buf_) + a.first);
+ auto strb = reinterpret_cast<const char *>(flatbuffers::vector_data(*buf_) + b.first);
+ return strncmp(stra, strb, (std::min)(a.second, b.second) + 1) < 0;
+ }
+ const std::vector<uint8_t> *buf_;
+ };
+
+ typedef std::set<size_t, KeyOffsetCompare> KeyOffsetMap;
+ typedef std::set<StringOffset, StringOffsetCompare> StringOffsetMap;
+
+ KeyOffsetMap key_pool;
+ StringOffsetMap string_pool;
+};
+
+} // namespace flexbuffers
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+#endif // FLATBUFFERS_FLEXBUFFERS_H_
diff --git a/onert-micro/externals/flatbuffers/grpc.h b/onert-micro/externals/flatbuffers/grpc.h
new file mode 100644
index 000000000..184c89e08
--- /dev/null
+++ b/onert-micro/externals/flatbuffers/grpc.h
@@ -0,0 +1,361 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2014 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLATBUFFERS_GRPC_H_
+#define FLATBUFFERS_GRPC_H_
+
+// Helper functionality to glue FlatBuffers and GRPC.
+
+#include "flatbuffers/flatbuffers.h"
+#include "grpc/byte_buffer_reader.h"
+#include "grpcpp/support/byte_buffer.h"
+
+namespace flatbuffers
+{
+namespace grpc
+{
+
+// Message is a typed wrapper around a buffer that manages the underlying
+// `grpc_slice` and also provides flatbuffers-specific helpers such as `Verify`
+// and `GetRoot`. Since it is backed by a `grpc_slice`, the underlying buffer
+// is refcounted and ownership is be managed automatically.
+template <class T> class Message
+{
+public:
+ Message() : slice_(grpc_empty_slice()) {}
+
+ Message(grpc_slice slice, bool add_ref) : slice_(add_ref ? grpc_slice_ref(slice) : slice) {}
+
+ Message &operator=(const Message &other) = delete;
+
+ Message(Message &&other) : slice_(other.slice_) { other.slice_ = grpc_empty_slice(); }
+
+ Message(const Message &other) = delete;
+
+ Message &operator=(Message &&other)
+ {
+ grpc_slice_unref(slice_);
+ slice_ = other.slice_;
+ other.slice_ = grpc_empty_slice();
+ return *this;
+ }
+
+ ~Message() { grpc_slice_unref(slice_); }
+
+ const uint8_t *mutable_data() const { return GRPC_SLICE_START_PTR(slice_); }
+
+ const uint8_t *data() const { return GRPC_SLICE_START_PTR(slice_); }
+
+ size_t size() const { return GRPC_SLICE_LENGTH(slice_); }
+
+ bool Verify() const
+ {
+ Verifier verifier(data(), size());
+ return verifier.VerifyBuffer<T>(nullptr);
+ }
+
+ T *GetMutableRoot() { return flatbuffers::GetMutableRoot<T>(mutable_data()); }
+
+ const T *GetRoot() const { return flatbuffers::GetRoot<T>(data()); }
+
+ // This is only intended for serializer use, or if you know what you're doing
+ const grpc_slice &BorrowSlice() const { return slice_; }
+
+private:
+ grpc_slice slice_;
+};
+
+class MessageBuilder;
+
+// SliceAllocator is a gRPC-specific allocator that uses the `grpc_slice`
+// refcounted slices to manage memory ownership. This makes it easy and
+// efficient to transfer buffers to gRPC.
+class SliceAllocator : public Allocator
+{
+public:
+ SliceAllocator() : slice_(grpc_empty_slice()) {}
+
+ SliceAllocator(const SliceAllocator &other) = delete;
+ SliceAllocator &operator=(const SliceAllocator &other) = delete;
+
+ SliceAllocator(SliceAllocator &&other) : slice_(grpc_empty_slice())
+ {
+ // default-construct and swap idiom
+ swap(other);
+ }
+
+ SliceAllocator &operator=(SliceAllocator &&other)
+ {
+ // move-construct and swap idiom
+ SliceAllocator temp(std::move(other));
+ swap(temp);
+ return *this;
+ }
+
+ void swap(SliceAllocator &other)
+ {
+ using std::swap;
+ swap(slice_, other.slice_);
+ }
+
+ virtual ~SliceAllocator() { grpc_slice_unref(slice_); }
+
+ virtual uint8_t *allocate(size_t size) override
+ {
+ FLATBUFFERS_ASSERT(GRPC_SLICE_IS_EMPTY(slice_));
+ slice_ = grpc_slice_malloc(size);
+ return GRPC_SLICE_START_PTR(slice_);
+ }
+
+ virtual void deallocate(uint8_t *p, size_t size) override
+ {
+ FLATBUFFERS_ASSERT(p == GRPC_SLICE_START_PTR(slice_));
+ FLATBUFFERS_ASSERT(size == GRPC_SLICE_LENGTH(slice_));
+ grpc_slice_unref(slice_);
+ slice_ = grpc_empty_slice();
+ }
+
+ virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size, size_t new_size,
+ size_t in_use_back, size_t in_use_front) override
+ {
+ FLATBUFFERS_ASSERT(old_p == GRPC_SLICE_START_PTR(slice_));
+ FLATBUFFERS_ASSERT(old_size == GRPC_SLICE_LENGTH(slice_));
+ FLATBUFFERS_ASSERT(new_size > old_size);
+ grpc_slice old_slice = slice_;
+ grpc_slice new_slice = grpc_slice_malloc(new_size);
+ uint8_t *new_p = GRPC_SLICE_START_PTR(new_slice);
+ memcpy_downward(old_p, old_size, new_p, new_size, in_use_back, in_use_front);
+ slice_ = new_slice;
+ grpc_slice_unref(old_slice);
+ return new_p;
+ }
+
+private:
+ grpc_slice &get_slice(uint8_t *p, size_t size)
+ {
+ FLATBUFFERS_ASSERT(p == GRPC_SLICE_START_PTR(slice_));
+ FLATBUFFERS_ASSERT(size == GRPC_SLICE_LENGTH(slice_));
+ return slice_;
+ }
+
+ grpc_slice slice_;
+
+ friend class MessageBuilder;
+};
+
+// SliceAllocatorMember is a hack to ensure that the MessageBuilder's
+// slice_allocator_ member is constructed before the FlatBufferBuilder, since
+// the allocator is used in the FlatBufferBuilder ctor.
+namespace detail
+{
+struct SliceAllocatorMember
+{
+ SliceAllocator slice_allocator_;
+};
+} // namespace detail
+
+// MessageBuilder is a gRPC-specific FlatBufferBuilder that uses SliceAllocator
+// to allocate gRPC buffers.
+class MessageBuilder : private detail::SliceAllocatorMember, public FlatBufferBuilder
+{
+public:
+ explicit MessageBuilder(uoffset_t initial_size = 1024)
+ : FlatBufferBuilder(initial_size, &slice_allocator_, false)
+ {
+ }
+
+ MessageBuilder(const MessageBuilder &other) = delete;
+ MessageBuilder &operator=(const MessageBuilder &other) = delete;
+
+ MessageBuilder(MessageBuilder &&other) : FlatBufferBuilder(1024, &slice_allocator_, false)
+ {
+ // Default construct and swap idiom.
+ Swap(other);
+ }
+
+ /// Create a MessageBuilder from a FlatBufferBuilder.
+ explicit MessageBuilder(FlatBufferBuilder &&src,
+ void (*dealloc)(void *, size_t) = &DefaultAllocator::dealloc)
+ : FlatBufferBuilder(1024, &slice_allocator_, false)
+ {
+ src.Swap(*this);
+ src.SwapBufAllocator(*this);
+ if (buf_.capacity())
+ {
+ uint8_t *buf = buf_.scratch_data(); // pointer to memory
+ size_t capacity = buf_.capacity(); // size of memory
+ slice_allocator_.slice_ = grpc_slice_new_with_len(buf, capacity, dealloc);
+ }
+ else
+ {
+ slice_allocator_.slice_ = grpc_empty_slice();
+ }
+ }
+
+ /// Move-assign a FlatBufferBuilder to a MessageBuilder.
+ /// Only FlatBufferBuilder with default allocator (basically, nullptr) is
+ /// supported.
+ MessageBuilder &operator=(FlatBufferBuilder &&src)
+ {
+ // Move construct a temporary and swap
+ MessageBuilder temp(std::move(src));
+ Swap(temp);
+ return *this;
+ }
+
+ MessageBuilder &operator=(MessageBuilder &&other)
+ {
+ // Move construct a temporary and swap
+ MessageBuilder temp(std::move(other));
+ Swap(temp);
+ return *this;
+ }
+
+ void Swap(MessageBuilder &other)
+ {
+ slice_allocator_.swap(other.slice_allocator_);
+ FlatBufferBuilder::Swap(other);
+ // After swapping the FlatBufferBuilder, we swap back the allocator, which
+ // restores the original allocator back in place. This is necessary because
+ // MessageBuilder's allocator is its own member (SliceAllocatorMember). The
+ // allocator passed to FlatBufferBuilder::vector_downward must point to this
+ // member.
+ buf_.swap_allocator(other.buf_);
+ }
+
+ // Releases the ownership of the buffer pointer.
+ // Returns the size, offset, and the original grpc_slice that
+ // allocated the buffer. Also see grpc_slice_unref().
+ uint8_t *ReleaseRaw(size_t &size, size_t &offset, grpc_slice &slice)
+ {
+ uint8_t *buf = FlatBufferBuilder::ReleaseRaw(size, offset);
+ slice = slice_allocator_.slice_;
+ slice_allocator_.slice_ = grpc_empty_slice();
+ return buf;
+ }
+
+ ~MessageBuilder() {}
+
+ // GetMessage extracts the subslice of the buffer corresponding to the
+ // flatbuffers-encoded region and wraps it in a `Message<T>` to handle buffer
+ // ownership.
+ template <class T> Message<T> GetMessage()
+ {
+ auto buf_data = buf_.scratch_data(); // pointer to memory
+ auto buf_size = buf_.capacity(); // size of memory
+ auto msg_data = buf_.data(); // pointer to msg
+ auto msg_size = buf_.size(); // size of msg
+ // Do some sanity checks on data/size
+ FLATBUFFERS_ASSERT(msg_data);
+ FLATBUFFERS_ASSERT(msg_size);
+ FLATBUFFERS_ASSERT(msg_data >= buf_data);
+ FLATBUFFERS_ASSERT(msg_data + msg_size <= buf_data + buf_size);
+ // Calculate offsets from the buffer start
+ auto begin = msg_data - buf_data;
+ auto end = begin + msg_size;
+ // Get the slice we are working with (no refcount change)
+ grpc_slice slice = slice_allocator_.get_slice(buf_data, buf_size);
+ // Extract a subslice of the existing slice (increment refcount)
+ grpc_slice subslice = grpc_slice_sub(slice, begin, end);
+ // Wrap the subslice in a `Message<T>`, but don't increment refcount
+ Message<T> msg(subslice, false);
+ return msg;
+ }
+
+ template <class T> Message<T> ReleaseMessage()
+ {
+ Message<T> msg = GetMessage<T>();
+ Reset();
+ return msg;
+ }
+
+private:
+ // SliceAllocator slice_allocator_; // part of SliceAllocatorMember
+};
+
+} // namespace grpc
+} // namespace flatbuffers
+
+namespace grpc
+{
+
+template <class T> class SerializationTraits<flatbuffers::grpc::Message<T>>
+{
+public:
+ static grpc::Status Serialize(const flatbuffers::grpc::Message<T> &msg, grpc_byte_buffer **buffer,
+ bool *own_buffer)
+ {
+ // We are passed in a `Message<T>`, which is a wrapper around a
+ // `grpc_slice`. We extract it here using `BorrowSlice()`. The const cast
+ // is necessary because the `grpc_raw_byte_buffer_create` func expects
+ // non-const slices in order to increment their refcounts.
+ grpc_slice *slice = const_cast<grpc_slice *>(&msg.BorrowSlice());
+ // Now use `grpc_raw_byte_buffer_create` to package the single slice into a
+ // `grpc_byte_buffer`, incrementing the refcount in the process.
+ *buffer = grpc_raw_byte_buffer_create(slice, 1);
+ *own_buffer = true;
+ return grpc::Status::OK;
+ }
+
+ // Deserialize by pulling the
+ static grpc::Status Deserialize(ByteBuffer *buf, flatbuffers::grpc::Message<T> *msg)
+ {
+ grpc_byte_buffer *buffer = *reinterpret_cast<grpc_byte_buffer **>(buf);
+ if (!buffer)
+ {
+ return ::grpc::Status(::grpc::StatusCode::INTERNAL, "No payload");
+ }
+ // Check if this is a single uncompressed slice.
+ if ((buffer->type == GRPC_BB_RAW) && (buffer->data.raw.compression == GRPC_COMPRESS_NONE) &&
+ (buffer->data.raw.slice_buffer.count == 1))
+ {
+ // If it is, then we can reference the `grpc_slice` directly.
+ grpc_slice slice = buffer->data.raw.slice_buffer.slices[0];
+ // We wrap a `Message<T>` around the slice, incrementing the refcount.
+ *msg = flatbuffers::grpc::Message<T>(slice, true);
+ }
+ else
+ {
+ // Otherwise, we need to use `grpc_byte_buffer_reader_readall` to read
+ // `buffer` into a single contiguous `grpc_slice`. The gRPC reader gives
+ // us back a new slice with the refcount already incremented.
+ grpc_byte_buffer_reader reader;
+ grpc_byte_buffer_reader_init(&reader, buffer);
+ grpc_slice slice = grpc_byte_buffer_reader_readall(&reader);
+ grpc_byte_buffer_reader_destroy(&reader);
+ // We wrap a `Message<T>` around the slice, but don't increment refcount
+ *msg = flatbuffers::grpc::Message<T>(slice, false);
+ }
+ grpc_byte_buffer_destroy(buffer);
+#if FLATBUFFERS_GRPC_DISABLE_AUTO_VERIFICATION
+ return ::grpc::Status::OK;
+#else
+ if (msg->Verify())
+ {
+ return ::grpc::Status::OK;
+ }
+ else
+ {
+ return ::grpc::Status(::grpc::StatusCode::INTERNAL, "Message verification failed");
+ }
+#endif
+ }
+};
+
+} // namespace grpc
+
+#endif // FLATBUFFERS_GRPC_H_
diff --git a/onert-micro/externals/flatbuffers/hash.h b/onert-micro/externals/flatbuffers/hash.h
new file mode 100644
index 000000000..a83c0ff20
--- /dev/null
+++ b/onert-micro/externals/flatbuffers/hash.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2015 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLATBUFFERS_HASH_H_
+#define FLATBUFFERS_HASH_H_
+
+#include <cstdint>
+#include <cstring>
+
+#include "flatbuffers/flatbuffers.h"
+
+namespace flatbuffers
+{
+
+template <typename T> struct FnvTraits
+{
+ static const T kFnvPrime;
+ static const T kOffsetBasis;
+};
+
+template <> struct FnvTraits<uint32_t>
+{
+ static const uint32_t kFnvPrime = 0x01000193;
+ static const uint32_t kOffsetBasis = 0x811C9DC5;
+};
+
+template <> struct FnvTraits<uint64_t>
+{
+ static const uint64_t kFnvPrime = 0x00000100000001b3ULL;
+ static const uint64_t kOffsetBasis = 0xcbf29ce484222645ULL;
+};
+
+template <typename T> T HashFnv1(const char *input)
+{
+ T hash = FnvTraits<T>::kOffsetBasis;
+ for (const char *c = input; *c; ++c)
+ {
+ hash *= FnvTraits<T>::kFnvPrime;
+ hash ^= static_cast<unsigned char>(*c);
+ }
+ return hash;
+}
+
+template <typename T> T HashFnv1a(const char *input)
+{
+ T hash = FnvTraits<T>::kOffsetBasis;
+ for (const char *c = input; *c; ++c)
+ {
+ hash ^= static_cast<unsigned char>(*c);
+ hash *= FnvTraits<T>::kFnvPrime;
+ }
+ return hash;
+}
+
+template <> inline uint16_t HashFnv1<uint16_t>(const char *input)
+{
+ uint32_t hash = HashFnv1<uint32_t>(input);
+ return (hash >> 16) ^ (hash & 0xffff);
+}
+
+template <> inline uint16_t HashFnv1a<uint16_t>(const char *input)
+{
+ uint32_t hash = HashFnv1a<uint32_t>(input);
+ return (hash >> 16) ^ (hash & 0xffff);
+}
+
+template <typename T> struct NamedHashFunction
+{
+ const char *name;
+
+ typedef T (*HashFunction)(const char *);
+ HashFunction function;
+};
+
+const NamedHashFunction<uint16_t> kHashFunctions16[] = {
+ {"fnv1_16", HashFnv1<uint16_t>},
+ {"fnv1a_16", HashFnv1a<uint16_t>},
+};
+
+const NamedHashFunction<uint32_t> kHashFunctions32[] = {
+ {"fnv1_32", HashFnv1<uint32_t>},
+ {"fnv1a_32", HashFnv1a<uint32_t>},
+};
+
+const NamedHashFunction<uint64_t> kHashFunctions64[] = {
+ {"fnv1_64", HashFnv1<uint64_t>},
+ {"fnv1a_64", HashFnv1a<uint64_t>},
+};
+
+inline NamedHashFunction<uint16_t>::HashFunction FindHashFunction16(const char *name)
+{
+ std::size_t size = sizeof(kHashFunctions16) / sizeof(kHashFunctions16[0]);
+ for (std::size_t i = 0; i < size; ++i)
+ {
+ if (std::strcmp(name, kHashFunctions16[i].name) == 0)
+ {
+ return kHashFunctions16[i].function;
+ }
+ }
+ return nullptr;
+}
+
+inline NamedHashFunction<uint32_t>::HashFunction FindHashFunction32(const char *name)
+{
+ std::size_t size = sizeof(kHashFunctions32) / sizeof(kHashFunctions32[0]);
+ for (std::size_t i = 0; i < size; ++i)
+ {
+ if (std::strcmp(name, kHashFunctions32[i].name) == 0)
+ {
+ return kHashFunctions32[i].function;
+ }
+ }
+ return nullptr;
+}
+
+inline NamedHashFunction<uint64_t>::HashFunction FindHashFunction64(const char *name)
+{
+ std::size_t size = sizeof(kHashFunctions64) / sizeof(kHashFunctions64[0]);
+ for (std::size_t i = 0; i < size; ++i)
+ {
+ if (std::strcmp(name, kHashFunctions64[i].name) == 0)
+ {
+ return kHashFunctions64[i].function;
+ }
+ }
+ return nullptr;
+}
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_HASH_H_
diff --git a/onert-micro/externals/flatbuffers/idl.h b/onert-micro/externals/flatbuffers/idl.h
new file mode 100644
index 000000000..de0a22ab1
--- /dev/null
+++ b/onert-micro/externals/flatbuffers/idl.h
@@ -0,0 +1,1145 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2014 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLATBUFFERS_IDL_H_
+#define FLATBUFFERS_IDL_H_
+
+#include <map>
+#include <memory>
+#include <stack>
+
+#include "flatbuffers/base.h"
+#include "flatbuffers/flatbuffers.h"
+#include "flatbuffers/flexbuffers.h"
+#include "flatbuffers/hash.h"
+#include "flatbuffers/reflection.h"
+
+#if !defined(FLATBUFFERS_CPP98_STL)
+#include <functional>
+#endif // !defined(FLATBUFFERS_CPP98_STL)
+
+// This file defines the data types representing a parsed IDL (Interface
+// Definition Language) / schema file.
+
+// Limits maximum depth of nested objects.
+// Prevents stack overflow while parse scheme, or json, or flexbuffer.
+#if !defined(FLATBUFFERS_MAX_PARSING_DEPTH)
+#define FLATBUFFERS_MAX_PARSING_DEPTH 64
+#endif
+
+namespace flatbuffers
+{
+
+// The order of these matters for Is*() functions below.
+// Additionally, Parser::ParseType assumes bool..string is a contiguous range
+// of type tokens.
+// clang-format off
+#define FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
+ TD(NONE, "", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8) \
+ TD(UTYPE, "", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8) /* begin scalar/int */ \
+ TD(BOOL, "bool", uint8_t, boolean,bool, bool, bool, bool, Boolean, Bool) \
+ TD(CHAR, "byte", int8_t, byte, int8, sbyte, int8, i8, Byte, Int8) \
+ TD(UCHAR, "ubyte", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8) \
+ TD(SHORT, "short", int16_t, short, int16, short, int16, i16, Short, Int16) \
+ TD(USHORT, "ushort", uint16_t, short, uint16, ushort, uint16, u16, UShort, UInt16) \
+ TD(INT, "int", int32_t, int, int32, int, int32, i32, Int, Int32) \
+ TD(UINT, "uint", uint32_t, int, uint32, uint, uint32, u32, UInt, UInt32) \
+ TD(LONG, "long", int64_t, long, int64, long, int64, i64, Long, Int64) \
+ TD(ULONG, "ulong", uint64_t, long, uint64, ulong, uint64, u64, ULong, UInt64) /* end int */ \
+ TD(FLOAT, "float", float, float, float32, float, float32, f32, Float, Float32) /* begin float */ \
+ TD(DOUBLE, "double", double, double, float64, double, float64, f64, Double, Double) /* end float/scalar */
+#define FLATBUFFERS_GEN_TYPES_POINTER(TD) \
+ TD(STRING, "string", Offset<void>, int, int, StringOffset, int, unused, Int, Offset<String>) \
+ TD(VECTOR, "", Offset<void>, int, int, VectorOffset, int, unused, Int, Offset<UOffset>) \
+ TD(STRUCT, "", Offset<void>, int, int, int, int, unused, Int, Offset<UOffset>) \
+ TD(UNION, "", Offset<void>, int, int, int, int, unused, Int, Offset<UOffset>)
+#define FLATBUFFERS_GEN_TYPE_ARRAY(TD) \
+ TD(ARRAY, "", int, int, int, int, int, unused, Int, Offset<UOffset>)
+// The fields are:
+// - enum
+// - FlatBuffers schema type.
+// - C++ type.
+// - Java type.
+// - Go type.
+// - C# / .Net type.
+// - Python type.
+// - Rust type.
+// - Kotlin type.
+
+// using these macros, we can now write code dealing with types just once, e.g.
+
+/*
+switch (type) {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
+ RTYPE, KTYPE) \
+ case BASE_TYPE_ ## ENUM: \
+ // do something specific to CTYPE here
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+}
+*/
+
+// If not all FLATBUFFERS_GEN_() arguments are necessary for implementation
+// of FLATBUFFERS_TD, you can use a variadic macro (with __VA_ARGS__ if needed).
+// In the above example, only CTYPE is used to generate the code, it can be rewritten:
+
+/*
+switch (type) {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+ case BASE_TYPE_ ## ENUM: \
+ // do something specific to CTYPE here
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+}
+*/
+
+#define FLATBUFFERS_GEN_TYPES(TD) \
+ FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
+ FLATBUFFERS_GEN_TYPES_POINTER(TD) \
+ FLATBUFFERS_GEN_TYPE_ARRAY(TD)
+
+// Create an enum for all the types above.
+#ifdef __GNUC__
+__extension__ // Stop GCC complaining about trailing comma with -Wpendantic.
+#endif
+enum BaseType {
+ #define FLATBUFFERS_TD(ENUM, ...) \
+ BASE_TYPE_ ## ENUM,
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+};
+
+#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+ static_assert(sizeof(CTYPE) <= sizeof(largest_scalar_t), \
+ "define largest_scalar_t as " #CTYPE);
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+#undef FLATBUFFERS_TD
+
+inline bool IsScalar (BaseType t) { return t >= BASE_TYPE_UTYPE &&
+ t <= BASE_TYPE_DOUBLE; }
+inline bool IsInteger(BaseType t) { return t >= BASE_TYPE_UTYPE &&
+ t <= BASE_TYPE_ULONG; }
+inline bool IsFloat (BaseType t) { return t == BASE_TYPE_FLOAT ||
+ t == BASE_TYPE_DOUBLE; }
+inline bool IsLong (BaseType t) { return t == BASE_TYPE_LONG ||
+ t == BASE_TYPE_ULONG; }
+inline bool IsBool (BaseType t) { return t == BASE_TYPE_BOOL; }
+inline bool IsOneByte(BaseType t) { return t >= BASE_TYPE_UTYPE &&
+ t <= BASE_TYPE_UCHAR; }
+
+inline bool IsUnsigned(BaseType t) {
+ return (t == BASE_TYPE_UTYPE) || (t == BASE_TYPE_UCHAR) ||
+ (t == BASE_TYPE_USHORT) || (t == BASE_TYPE_UINT) ||
+ (t == BASE_TYPE_ULONG);
+}
+
+// clang-format on
+
+extern const char *const kTypeNames[];
+extern const char kTypeSizes[];
+
+inline size_t SizeOf(BaseType t) { return kTypeSizes[t]; }
+
+struct StructDef;
+struct EnumDef;
+class Parser;
+
+// Represents any type in the IDL, which is a combination of the BaseType
+// and additional information for vectors/structs_.
+struct Type
+{
+ explicit Type(BaseType _base_type = BASE_TYPE_NONE, StructDef *_sd = nullptr,
+ EnumDef *_ed = nullptr, uint16_t _fixed_length = 0)
+ : base_type(_base_type), element(BASE_TYPE_NONE), struct_def(_sd), enum_def(_ed),
+ fixed_length(_fixed_length)
+ {
+ }
+
+ bool operator==(const Type &o)
+ {
+ return base_type == o.base_type && element == o.element && struct_def == o.struct_def &&
+ enum_def == o.enum_def;
+ }
+
+ Type VectorType() const { return Type(element, struct_def, enum_def, fixed_length); }
+
+ Offset<reflection::Type> Serialize(FlatBufferBuilder *builder) const;
+
+ bool Deserialize(const Parser &parser, const reflection::Type *type);
+
+ BaseType base_type;
+ BaseType element; // only set if t == BASE_TYPE_VECTOR
+ StructDef *struct_def; // only set if t or element == BASE_TYPE_STRUCT
+ EnumDef *enum_def; // set if t == BASE_TYPE_UNION / BASE_TYPE_UTYPE,
+ // or for an integral type derived from an enum.
+ uint16_t fixed_length; // only set if t == BASE_TYPE_ARRAY
+};
+
+// Represents a parsed scalar value, it's type, and field offset.
+struct Value
+{
+ Value() : constant("0"), offset(static_cast<voffset_t>(~(static_cast<voffset_t>(0U)))) {}
+ Type type;
+ std::string constant;
+ voffset_t offset;
+};
+
+// Helper class that retains the original order of a set of identifiers and
+// also provides quick lookup.
+template <typename T> class SymbolTable
+{
+public:
+ ~SymbolTable()
+ {
+ for (auto it = vec.begin(); it != vec.end(); ++it)
+ {
+ delete *it;
+ }
+ }
+
+ bool Add(const std::string &name, T *e)
+ {
+ vector_emplace_back(&vec, e);
+ auto it = dict.find(name);
+ if (it != dict.end())
+ return true;
+ dict[name] = e;
+ return false;
+ }
+
+ void Move(const std::string &oldname, const std::string &newname)
+ {
+ auto it = dict.find(oldname);
+ if (it != dict.end())
+ {
+ auto obj = it->second;
+ dict.erase(it);
+ dict[newname] = obj;
+ }
+ else
+ {
+ FLATBUFFERS_ASSERT(false);
+ }
+ }
+
+ T *Lookup(const std::string &name) const
+ {
+ auto it = dict.find(name);
+ return it == dict.end() ? nullptr : it->second;
+ }
+
+public:
+ std::map<std::string, T *> dict; // quick lookup
+ std::vector<T *> vec; // Used to iterate in order of insertion
+};
+
+// A name space, as set in the schema.
+struct Namespace
+{
+ Namespace() : from_table(0) {}
+
+ // Given a (potentially unqualified) name, return the "fully qualified" name
+ // which has a full namespaced descriptor.
+ // With max_components you can request less than the number of components
+ // the current namespace has.
+ std::string GetFullyQualifiedName(const std::string &name, size_t max_components = 1000) const;
+
+ std::vector<std::string> components;
+ size_t from_table; // Part of the namespace corresponds to a message/table.
+};
+
+inline bool operator<(const Namespace &a, const Namespace &b)
+{
+ size_t min_size = std::min(a.components.size(), b.components.size());
+ for (size_t i = 0; i < min_size; ++i)
+ {
+ if (a.components[i] != b.components[i])
+ return a.components[i] < b.components[i];
+ }
+ return a.components.size() < b.components.size();
+}
+
+// Base class for all definition types (fields, structs_, enums_).
+struct Definition
+{
+ Definition()
+ : generated(false), defined_namespace(nullptr), serialized_location(0), index(-1), refcount(1)
+ {
+ }
+
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
+ SerializeAttributes(FlatBufferBuilder *builder, const Parser &parser) const;
+
+ bool DeserializeAttributes(Parser &parser, const Vector<Offset<reflection::KeyValue>> *attrs);
+
+ std::string name;
+ std::string file;
+ std::vector<std::string> doc_comment;
+ SymbolTable<Value> attributes;
+ bool generated; // did we already output code for this definition?
+ Namespace *defined_namespace; // Where it was defined.
+
+ // For use with Serialize()
+ uoffset_t serialized_location;
+ int index; // Inside the vector it is stored.
+ int refcount;
+};
+
+struct FieldDef : public Definition
+{
+ FieldDef()
+ : deprecated(false), key(false), shared(false), native_inline(false), flexbuffer(false),
+ presence(kDefault), nested_flatbuffer(NULL), padding(0)
+ {
+ }
+
+ Offset<reflection::Field> Serialize(FlatBufferBuilder *builder, uint16_t id,
+ const Parser &parser) const;
+
+ bool Deserialize(Parser &parser, const reflection::Field *field);
+
+ bool IsScalarOptional() const { return IsScalar(value.type.base_type) && IsOptional(); }
+ bool IsOptional() const { return presence == kOptional; }
+ bool IsRequired() const { return presence == kRequired; }
+ bool IsDefault() const { return presence == kDefault; }
+
+ Value value;
+ bool deprecated; // Field is allowed to be present in old data, but can't be.
+ // written in new data nor accessed in new code.
+ bool key; // Field functions as a key for creating sorted vectors.
+ bool shared; // Field will be using string pooling (i.e. CreateSharedString)
+ // as default serialization behavior if field is a string.
+ bool native_inline; // Field will be defined inline (instead of as a pointer)
+ // for native tables if field is a struct.
+ bool flexbuffer; // This field contains FlexBuffer data.
+
+ enum Presence
+ {
+ // Field must always be present.
+ kRequired,
+ // Non-presence should be signalled to and controlled by users.
+ kOptional,
+ // Non-presence is hidden from users.
+ // Implementations may omit writing default values.
+ kDefault,
+ };
+ Presence static MakeFieldPresence(bool optional, bool required)
+ {
+ FLATBUFFERS_ASSERT(!(required && optional));
+ // clang-format off
+ return required ? FieldDef::kRequired
+ : optional ? FieldDef::kOptional
+ : FieldDef::kDefault;
+ // clang-format on
+ }
+ Presence presence;
+
+ StructDef *nested_flatbuffer; // This field contains nested FlatBuffer data.
+ size_t padding; // Bytes to always pad after this field.
+};
+
+struct StructDef : public Definition
+{
+ StructDef()
+ : fixed(false), predecl(true), sortbysize(true), has_key(false), minalign(1), bytesize(0)
+ {
+ }
+
+ void PadLastField(size_t min_align)
+ {
+ auto padding = PaddingBytes(bytesize, min_align);
+ bytesize += padding;
+ if (fields.vec.size())
+ fields.vec.back()->padding = padding;
+ }
+
+ Offset<reflection::Object> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
+
+ bool Deserialize(Parser &parser, const reflection::Object *object);
+
+ SymbolTable<FieldDef> fields;
+
+ bool fixed; // If it's struct, not a table.
+ bool predecl; // If it's used before it was defined.
+ bool sortbysize; // Whether fields come in the declaration or size order.
+ bool has_key; // It has a key field.
+ size_t minalign; // What the whole object needs to be aligned to.
+ size_t bytesize; // Size if fixed.
+
+ flatbuffers::unique_ptr<std::string> original_location;
+};
+
+struct EnumDef;
+struct EnumValBuilder;
+
+struct EnumVal
+{
+ Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
+
+ bool Deserialize(const Parser &parser, const reflection::EnumVal *val);
+
+ uint64_t GetAsUInt64() const { return static_cast<uint64_t>(value); }
+ int64_t GetAsInt64() const { return value; }
+ bool IsZero() const { return 0 == value; }
+ bool IsNonZero() const { return !IsZero(); }
+
+ std::string name;
+ std::vector<std::string> doc_comment;
+ Type union_type;
+
+private:
+ friend EnumDef;
+ friend EnumValBuilder;
+ friend bool operator==(const EnumVal &lhs, const EnumVal &rhs);
+
+ EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {}
+ EnumVal() : value(0) {}
+
+ int64_t value;
+};
+
+struct EnumDef : public Definition
+{
+ EnumDef() : is_union(false), uses_multiple_type_instances(false) {}
+
+ Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
+
+ bool Deserialize(Parser &parser, const reflection::Enum *values);
+
+ template <typename T> void ChangeEnumValue(EnumVal *ev, T new_val);
+ void SortByValue();
+ void RemoveDuplicates();
+
+ std::string AllFlags() const;
+ const EnumVal *MinValue() const;
+ const EnumVal *MaxValue() const;
+ // Returns the number of integer steps from v1 to v2.
+ uint64_t Distance(const EnumVal *v1, const EnumVal *v2) const;
+ // Returns the number of integer steps from Min to Max.
+ uint64_t Distance() const { return Distance(MinValue(), MaxValue()); }
+
+ EnumVal *ReverseLookup(int64_t enum_idx, bool skip_union_default = false) const;
+ EnumVal *FindByValue(const std::string &constant) const;
+
+ std::string ToString(const EnumVal &ev) const
+ {
+ return IsUInt64() ? NumToString(ev.GetAsUInt64()) : NumToString(ev.GetAsInt64());
+ }
+
+ size_t size() const { return vals.vec.size(); }
+
+ const std::vector<EnumVal *> &Vals() const { return vals.vec; }
+
+ const EnumVal *Lookup(const std::string &enum_name) const { return vals.Lookup(enum_name); }
+
+ bool is_union;
+ // Type is a union which uses type aliases where at least one type is
+ // available under two different names.
+ bool uses_multiple_type_instances;
+ Type underlying_type;
+
+private:
+ bool IsUInt64() const { return (BASE_TYPE_ULONG == underlying_type.base_type); }
+
+ friend EnumValBuilder;
+ SymbolTable<EnumVal> vals;
+};
+
+inline bool IsString(const Type &type) { return type.base_type == BASE_TYPE_STRING; }
+
+inline bool IsStruct(const Type &type)
+{
+ return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed;
+}
+
+inline bool IsUnion(const Type &type)
+{
+ return type.enum_def != nullptr && type.enum_def->is_union;
+}
+
+inline bool IsVector(const Type &type) { return type.base_type == BASE_TYPE_VECTOR; }
+
+inline bool IsArray(const Type &type) { return type.base_type == BASE_TYPE_ARRAY; }
+
+inline bool IsSeries(const Type &type) { return IsVector(type) || IsArray(type); }
+
+inline bool IsEnum(const Type &type)
+{
+ return type.enum_def != nullptr && IsInteger(type.base_type);
+}
+
+inline size_t InlineSize(const Type &type)
+{
+ return IsStruct(type) ? type.struct_def->bytesize
+ : (IsArray(type) ? InlineSize(type.VectorType()) * type.fixed_length
+ : SizeOf(type.base_type));
+}
+
+inline size_t InlineAlignment(const Type &type)
+{
+ if (IsStruct(type))
+ {
+ return type.struct_def->minalign;
+ }
+ else if (IsArray(type))
+ {
+ return IsStruct(type.VectorType()) ? type.struct_def->minalign : SizeOf(type.element);
+ }
+ else
+ {
+ return SizeOf(type.base_type);
+ }
+}
+inline bool operator==(const EnumVal &lhs, const EnumVal &rhs) { return lhs.value == rhs.value; }
+inline bool operator!=(const EnumVal &lhs, const EnumVal &rhs) { return !(lhs == rhs); }
+
+inline bool EqualByName(const Type &a, const Type &b)
+{
+ return a.base_type == b.base_type && a.element == b.element &&
+ (a.struct_def == b.struct_def || a.struct_def->name == b.struct_def->name) &&
+ (a.enum_def == b.enum_def || a.enum_def->name == b.enum_def->name);
+}
+
+struct RPCCall : public Definition
+{
+ Offset<reflection::RPCCall> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
+
+ bool Deserialize(Parser &parser, const reflection::RPCCall *call);
+
+ StructDef *request, *response;
+};
+
+struct ServiceDef : public Definition
+{
+ Offset<reflection::Service> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
+ bool Deserialize(Parser &parser, const reflection::Service *service);
+
+ SymbolTable<RPCCall> calls;
+};
+
+// Container of options that may apply to any of the source/text generators.
+struct IDLOptions
+{
+ bool gen_jvmstatic;
+ // Use flexbuffers instead for binary and text generation
+ bool use_flexbuffers;
+ bool strict_json;
+ bool output_default_scalars_in_json;
+ int indent_step;
+ bool output_enum_identifiers;
+ bool prefixed_enums;
+ bool scoped_enums;
+ bool include_dependence_headers;
+ bool mutable_buffer;
+ bool one_file;
+ bool proto_mode;
+ bool proto_oneof_union;
+ bool generate_all;
+ bool skip_unexpected_fields_in_json;
+ bool generate_name_strings;
+ bool generate_object_based_api;
+ bool gen_compare;
+ std::string cpp_object_api_pointer_type;
+ std::string cpp_object_api_string_type;
+ bool cpp_object_api_string_flexible_constructor;
+ bool cpp_direct_copy;
+ bool gen_nullable;
+ bool java_checkerframework;
+ bool gen_generated;
+ std::string object_prefix;
+ std::string object_suffix;
+ bool union_value_namespacing;
+ bool allow_non_utf8;
+ bool natural_utf8;
+ std::string include_prefix;
+ bool keep_include_path;
+ bool binary_schema_comments;
+ bool binary_schema_builtins;
+ bool binary_schema_gen_embed;
+ std::string go_import;
+ std::string go_namespace;
+ bool protobuf_ascii_alike;
+ bool size_prefixed;
+ std::string root_type;
+ bool force_defaults;
+ bool java_primitive_has_method;
+ bool cs_gen_json_serializer;
+ std::vector<std::string> cpp_includes;
+ std::string cpp_std;
+ bool cpp_static_reflection;
+ std::string proto_namespace_suffix;
+ std::string filename_suffix;
+ std::string filename_extension;
+ bool no_warnings;
+
+ // Possible options for the more general generator below.
+ enum Language
+ {
+ kJava = 1 << 0,
+ kCSharp = 1 << 1,
+ kGo = 1 << 2,
+ kCpp = 1 << 3,
+ kPython = 1 << 5,
+ kPhp = 1 << 6,
+ kJson = 1 << 7,
+ kBinary = 1 << 8,
+ kTs = 1 << 9,
+ kJsonSchema = 1 << 10,
+ kDart = 1 << 11,
+ kLua = 1 << 12,
+ kLobster = 1 << 13,
+ kRust = 1 << 14,
+ kKotlin = 1 << 15,
+ kSwift = 1 << 16,
+ kMAX
+ };
+
+ Language lang;
+
+ enum MiniReflect
+ {
+ kNone,
+ kTypes,
+ kTypesAndNames
+ };
+
+ MiniReflect mini_reflect;
+
+ // If set, require all fields in a table to be explicitly numbered.
+ bool require_explicit_ids;
+
+ // The corresponding language bit will be set if a language is included
+ // for code generation.
+ unsigned long lang_to_generate;
+
+ // If set (default behavior), empty string fields will be set to nullptr to
+ // make the flatbuffer more compact.
+ bool set_empty_strings_to_null;
+
+ // If set (default behavior), empty vector fields will be set to nullptr to
+ // make the flatbuffer more compact.
+ bool set_empty_vectors_to_null;
+
+ IDLOptions()
+ : gen_jvmstatic(false), use_flexbuffers(false), strict_json(false),
+ output_default_scalars_in_json(false), indent_step(2), output_enum_identifiers(true),
+ prefixed_enums(true), scoped_enums(false), include_dependence_headers(true),
+ mutable_buffer(false), one_file(false), proto_mode(false), proto_oneof_union(false),
+ generate_all(false), skip_unexpected_fields_in_json(false), generate_name_strings(false),
+ generate_object_based_api(false), gen_compare(false),
+ cpp_object_api_pointer_type("std::unique_ptr"),
+ cpp_object_api_string_flexible_constructor(false), cpp_direct_copy(true), gen_nullable(false),
+ java_checkerframework(false), gen_generated(false), object_suffix("T"),
+ union_value_namespacing(true), allow_non_utf8(false), natural_utf8(false),
+ keep_include_path(false), binary_schema_comments(false), binary_schema_builtins(false),
+ binary_schema_gen_embed(false), protobuf_ascii_alike(false), size_prefixed(false),
+ force_defaults(false), java_primitive_has_method(false), cs_gen_json_serializer(false),
+ cpp_static_reflection(false), filename_suffix("_generated"), filename_extension(),
+ no_warnings(false), lang(IDLOptions::kJava), mini_reflect(IDLOptions::kNone),
+ require_explicit_ids(false), lang_to_generate(0), set_empty_strings_to_null(true),
+ set_empty_vectors_to_null(true)
+ {
+ }
+};
+
+// This encapsulates where the parser is in the current source file.
+struct ParserState
+{
+ ParserState()
+ : cursor_(nullptr), line_start_(nullptr), line_(0), token_(-1),
+ attr_is_trivial_ascii_string_(true)
+ {
+ }
+
+protected:
+ void ResetState(const char *source)
+ {
+ cursor_ = source;
+ line_ = 0;
+ MarkNewLine();
+ }
+
+ void MarkNewLine()
+ {
+ line_start_ = cursor_;
+ line_ += 1;
+ }
+
+ int64_t CursorPosition() const
+ {
+ FLATBUFFERS_ASSERT(cursor_ && line_start_ && cursor_ >= line_start_);
+ return static_cast<int64_t>(cursor_ - line_start_);
+ }
+
+ const char *cursor_;
+ const char *line_start_;
+ int line_; // the current line being parsed
+ int token_;
+
+ // Flag: text in attribute_ is true ASCII string without escape
+ // sequences. Only printable ASCII (without [\t\r\n]).
+ // Used for number-in-string (and base64 string in future).
+ bool attr_is_trivial_ascii_string_;
+ std::string attribute_;
+ std::vector<std::string> doc_comment_;
+};
+
+// A way to make error propagation less error prone by requiring values to be
+// checked.
+// Once you create a value of this type you must either:
+// - Call Check() on it.
+// - Copy or assign it to another value.
+// Failure to do so leads to an assert.
+// This guarantees that this as return value cannot be ignored.
+class CheckedError
+{
+public:
+ explicit CheckedError(bool error) : is_error_(error), has_been_checked_(false) {}
+
+ CheckedError &operator=(const CheckedError &other)
+ {
+ is_error_ = other.is_error_;
+ has_been_checked_ = false;
+ other.has_been_checked_ = true;
+ return *this;
+ }
+
+ CheckedError(const CheckedError &other)
+ {
+ *this = other; // Use assignment operator.
+ }
+
+ ~CheckedError() { FLATBUFFERS_ASSERT(has_been_checked_); }
+
+ bool Check()
+ {
+ has_been_checked_ = true;
+ return is_error_;
+ }
+
+private:
+ bool is_error_;
+ mutable bool has_been_checked_;
+};
+
+// Additionally, in GCC we can get these errors statically, for additional
+// assurance:
+// clang-format off
+#ifdef __GNUC__
+#define FLATBUFFERS_CHECKED_ERROR CheckedError \
+ __attribute__((warn_unused_result))
+#else
+#define FLATBUFFERS_CHECKED_ERROR CheckedError
+#endif
+// clang-format on
+
+class Parser : public ParserState
+{
+public:
+ explicit Parser(const IDLOptions &options = IDLOptions())
+ : current_namespace_(nullptr), empty_namespace_(nullptr),
+ flex_builder_(256, flexbuffers::BUILDER_FLAG_SHARE_ALL), root_struct_def_(nullptr),
+ opts(options), uses_flexbuffers_(false), advanced_features_(0), source_(nullptr),
+ anonymous_counter_(0), parse_depth_counter_(0)
+ {
+ if (opts.force_defaults)
+ {
+ builder_.ForceDefaults(true);
+ }
+ // Start out with the empty namespace being current.
+ empty_namespace_ = new Namespace();
+ namespaces_.push_back(empty_namespace_);
+ current_namespace_ = empty_namespace_;
+ known_attributes_["deprecated"] = true;
+ known_attributes_["required"] = true;
+ known_attributes_["key"] = true;
+ known_attributes_["shared"] = true;
+ known_attributes_["hash"] = true;
+ known_attributes_["id"] = true;
+ known_attributes_["force_align"] = true;
+ known_attributes_["bit_flags"] = true;
+ known_attributes_["original_order"] = true;
+ known_attributes_["nested_flatbuffer"] = true;
+ known_attributes_["csharp_partial"] = true;
+ known_attributes_["streaming"] = true;
+ known_attributes_["idempotent"] = true;
+ known_attributes_["cpp_type"] = true;
+ known_attributes_["cpp_ptr_type"] = true;
+ known_attributes_["cpp_ptr_type_get"] = true;
+ known_attributes_["cpp_str_type"] = true;
+ known_attributes_["cpp_str_flex_ctor"] = true;
+ known_attributes_["native_inline"] = true;
+ known_attributes_["native_custom_alloc"] = true;
+ known_attributes_["native_type"] = true;
+ known_attributes_["native_type_pack_name"] = true;
+ known_attributes_["native_default"] = true;
+ known_attributes_["flexbuffer"] = true;
+ known_attributes_["private"] = true;
+ }
+
+ ~Parser()
+ {
+ for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it)
+ {
+ delete *it;
+ }
+ }
+
+ // Parse the string containing either schema or JSON data, which will
+ // populate the SymbolTable's or the FlatBufferBuilder above.
+ // include_paths is used to resolve any include statements, and typically
+ // should at least include the project path (where you loaded source_ from).
+ // include_paths must be nullptr terminated if specified.
+ // If include_paths is nullptr, it will attempt to load from the current
+ // directory.
+ // If the source was loaded from a file and isn't an include file,
+ // supply its name in source_filename.
+ // All paths specified in this call must be in posix format, if you accept
+ // paths from user input, please call PosixPath on them first.
+ bool Parse(const char *_source, const char **include_paths = nullptr,
+ const char *source_filename = nullptr);
+
+ bool ParseJson(const char *json, const char *json_filename = nullptr);
+
+ // Set the root type. May override the one set in the schema.
+ bool SetRootType(const char *name);
+
+ // Mark all definitions as already having code generated.
+ void MarkGenerated();
+
+ // Get the files recursively included by the given file. The returned
+ // container will have at least the given file.
+ std::set<std::string> GetIncludedFilesRecursive(const std::string &file_name) const;
+
+ // Fills builder_ with a binary version of the schema parsed.
+ // See reflection/reflection.fbs
+ void Serialize();
+
+ // Deserialize a schema buffer
+ bool Deserialize(const uint8_t *buf, const size_t size);
+
+ // Fills internal structure as if the schema passed had been loaded by parsing
+ // with Parse except that included filenames will not be populated.
+ bool Deserialize(const reflection::Schema *schema);
+
+ Type *DeserializeType(const reflection::Type *type);
+
+ // Checks that the schema represented by this parser is a safe evolution
+ // of the schema provided. Returns non-empty error on any problems.
+ std::string ConformTo(const Parser &base);
+
+ // Similar to Parse(), but now only accepts JSON to be parsed into a
+ // FlexBuffer.
+ bool ParseFlexBuffer(const char *source, const char *source_filename,
+ flexbuffers::Builder *builder);
+
+ StructDef *LookupStruct(const std::string &id) const;
+ StructDef *LookupStructThruParentNamespaces(const std::string &id) const;
+
+ std::string UnqualifiedName(const std::string &fullQualifiedName);
+
+ FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
+
+ // @brief Verify that any of 'opts.lang_to_generate' supports Optional scalars
+ // in a schema.
+ // @param opts Options used to parce a schema and generate code.
+ static bool SupportsOptionalScalars(const flatbuffers::IDLOptions &opts);
+
+private:
+ class ParseDepthGuard;
+
+ void Message(const std::string &msg);
+ void Warning(const std::string &msg);
+ FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, uint64_t *val);
+ FLATBUFFERS_CHECKED_ERROR Next();
+ FLATBUFFERS_CHECKED_ERROR SkipByteOrderMark();
+ bool Is(int t) const;
+ bool IsIdent(const char *id) const;
+ FLATBUFFERS_CHECKED_ERROR Expect(int t);
+ std::string TokenToStringId(int t) const;
+ EnumDef *LookupEnum(const std::string &id);
+ FLATBUFFERS_CHECKED_ERROR ParseNamespacing(std::string *id, std::string *last);
+ FLATBUFFERS_CHECKED_ERROR ParseTypeIdent(Type &type);
+ FLATBUFFERS_CHECKED_ERROR ParseType(Type &type);
+ FLATBUFFERS_CHECKED_ERROR AddField(StructDef &struct_def, const std::string &name,
+ const Type &type, FieldDef **dest);
+ FLATBUFFERS_CHECKED_ERROR ParseField(StructDef &struct_def);
+ FLATBUFFERS_CHECKED_ERROR ParseString(Value &val, bool use_string_pooling);
+ FLATBUFFERS_CHECKED_ERROR ParseComma();
+ FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field, size_t parent_fieldn,
+ const StructDef *parent_struct_def, uoffset_t count,
+ bool inside_vector = false);
+ template <typename F>
+ FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn, const StructDef *struct_def,
+ F body);
+ FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def, std::string *value,
+ uoffset_t *ovalue);
+ void SerializeStruct(const StructDef &struct_def, const Value &val);
+ void SerializeStruct(FlatBufferBuilder &builder, const StructDef &struct_def, const Value &val);
+ template <typename F> FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(uoffset_t &count, F body);
+ FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue, FieldDef *field,
+ size_t fieldn);
+ FLATBUFFERS_CHECKED_ERROR ParseArray(Value &array);
+ FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(Value &val, FieldDef *field, size_t fieldn,
+ const StructDef *parent_struct_def);
+ FLATBUFFERS_CHECKED_ERROR ParseMetaData(SymbolTable<Value> *attributes);
+ FLATBUFFERS_CHECKED_ERROR TryTypedValue(const std::string *name, int dtoken, bool check, Value &e,
+ BaseType req, bool *destmatch);
+ FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef *field);
+ FLATBUFFERS_CHECKED_ERROR TokenError();
+ FLATBUFFERS_CHECKED_ERROR ParseSingleValue(const std::string *name, Value &e, bool check_now);
+ FLATBUFFERS_CHECKED_ERROR ParseFunction(const std::string *name, Value &e);
+ FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(const Type &type, std::string *result);
+ StructDef *LookupCreateStruct(const std::string &name, bool create_if_new = true,
+ bool definition = false);
+ FLATBUFFERS_CHECKED_ERROR ParseEnum(bool is_union, EnumDef **dest);
+ FLATBUFFERS_CHECKED_ERROR ParseNamespace();
+ FLATBUFFERS_CHECKED_ERROR StartStruct(const std::string &name, StructDef **dest);
+ FLATBUFFERS_CHECKED_ERROR StartEnum(const std::string &name, bool is_union, EnumDef **dest);
+ FLATBUFFERS_CHECKED_ERROR ParseDecl();
+ FLATBUFFERS_CHECKED_ERROR ParseService();
+ FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def, bool isextend,
+ bool inside_oneof);
+ FLATBUFFERS_CHECKED_ERROR ParseProtoOption();
+ FLATBUFFERS_CHECKED_ERROR ParseProtoKey();
+ FLATBUFFERS_CHECKED_ERROR ParseProtoDecl();
+ FLATBUFFERS_CHECKED_ERROR ParseProtoCurliesOrIdent();
+ FLATBUFFERS_CHECKED_ERROR ParseTypeFromProtoType(Type *type);
+ FLATBUFFERS_CHECKED_ERROR SkipAnyJsonValue();
+ FLATBUFFERS_CHECKED_ERROR ParseFlexBufferNumericConstant(flexbuffers::Builder *builder);
+ FLATBUFFERS_CHECKED_ERROR ParseFlexBufferValue(flexbuffers::Builder *builder);
+ FLATBUFFERS_CHECKED_ERROR StartParseFile(const char *source, const char *source_filename);
+ FLATBUFFERS_CHECKED_ERROR ParseRoot(const char *_source, const char **include_paths,
+ const char *source_filename);
+ FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source, const char **include_paths,
+ const char *source_filename, const char *include_filename);
+ FLATBUFFERS_CHECKED_ERROR DoParseJson();
+ FLATBUFFERS_CHECKED_ERROR CheckClash(std::vector<FieldDef *> &fields, StructDef *struct_def,
+ const char *suffix, BaseType baseType);
+ FLATBUFFERS_CHECKED_ERROR ParseAlignAttribute(const std::string &align_constant, size_t min_align,
+ size_t *align);
+
+ bool SupportsAdvancedUnionFeatures() const;
+ bool SupportsAdvancedArrayFeatures() const;
+ bool SupportsOptionalScalars() const;
+ bool SupportsDefaultVectorsAndStrings() const;
+ Namespace *UniqueNamespace(Namespace *ns);
+
+ FLATBUFFERS_CHECKED_ERROR RecurseError();
+ template <typename F> CheckedError Recurse(F f);
+
+public:
+ SymbolTable<Type> types_;
+ SymbolTable<StructDef> structs_;
+ SymbolTable<EnumDef> enums_;
+ SymbolTable<ServiceDef> services_;
+ std::vector<Namespace *> namespaces_;
+ Namespace *current_namespace_;
+ Namespace *empty_namespace_;
+ std::string error_; // User readable error_ if Parse() == false
+
+ FlatBufferBuilder builder_; // any data contained in the file
+ flexbuffers::Builder flex_builder_;
+ flexbuffers::Reference flex_root_;
+ StructDef *root_struct_def_;
+ std::string file_identifier_;
+ std::string file_extension_;
+
+ std::map<uint64_t, std::string> included_files_;
+ std::map<std::string, std::set<std::string>> files_included_per_file_;
+ std::vector<std::string> native_included_files_;
+
+ std::map<std::string, bool> known_attributes_;
+
+ IDLOptions opts;
+ bool uses_flexbuffers_;
+
+ uint64_t advanced_features_;
+
+private:
+ const char *source_;
+
+ std::string file_being_parsed_;
+
+ std::vector<std::pair<Value, FieldDef *>> field_stack_;
+
+ int anonymous_counter_;
+ int parse_depth_counter_; // stack-overflow guard
+};
+
+// Utility functions for multiple generators:
+
+extern std::string MakeCamel(const std::string &in, bool first = true);
+
+extern std::string MakeScreamingCamel(const std::string &in);
+
+// Generate text (JSON) from a given FlatBuffer, and a given Parser
+// object that has been populated with the corresponding schema.
+// If ident_step is 0, no indentation will be generated. Additionally,
+// if it is less than 0, no linefeeds will be generated either.
+// See idl_gen_text.cpp.
+// strict_json adds "quotes" around field names if true.
+// If the flatbuffer cannot be encoded in JSON (e.g., it contains non-UTF-8
+// byte arrays in String values), returns false.
+extern bool GenerateTextFromTable(const Parser &parser, const void *table,
+ const std::string &tablename, std::string *text);
+extern bool GenerateText(const Parser &parser, const void *flatbuffer, std::string *text);
+extern bool GenerateTextFile(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate Json schema to string
+// See idl_gen_json_schema.cpp.
+extern bool GenerateJsonSchema(const Parser &parser, std::string *json);
+
+// Generate binary files from a given FlatBuffer, and a given Parser
+// object that has been populated with the corresponding schema.
+// See code_generators.cpp.
+extern bool GenerateBinary(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate a C++ header from the definitions in the Parser object.
+// See idl_gen_cpp.
+extern bool GenerateCPP(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate C# files from the definitions in the Parser object.
+// See idl_gen_csharp.cpp.
+extern bool GenerateCSharp(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+extern bool GenerateDart(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate Java files from the definitions in the Parser object.
+// See idl_gen_java.cpp.
+extern bool GenerateJava(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate JavaScript or TypeScript code from the definitions in the Parser
+// object. See idl_gen_js.
+extern bool GenerateTS(const Parser &parser, const std::string &path, const std::string &file_name);
+
+// Generate Go files from the definitions in the Parser object.
+// See idl_gen_go.cpp.
+extern bool GenerateGo(const Parser &parser, const std::string &path, const std::string &file_name);
+
+// Generate Php code from the definitions in the Parser object.
+// See idl_gen_php.
+extern bool GeneratePhp(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate Python files from the definitions in the Parser object.
+// See idl_gen_python.cpp.
+extern bool GeneratePython(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate Lobster files from the definitions in the Parser object.
+// See idl_gen_lobster.cpp.
+extern bool GenerateLobster(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate Lua files from the definitions in the Parser object.
+// See idl_gen_lua.cpp.
+extern bool GenerateLua(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate Rust files from the definitions in the Parser object.
+// See idl_gen_rust.cpp.
+extern bool GenerateRust(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate Json schema file
+// See idl_gen_json_schema.cpp.
+extern bool GenerateJsonSchema(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+extern bool GenerateKotlin(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate Swift classes.
+// See idl_gen_swift.cpp
+extern bool GenerateSwift(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate a schema file from the internal representation, useful after
+// parsing a .proto schema.
+extern std::string GenerateFBS(const Parser &parser, const std::string &file_name);
+extern bool GenerateFBS(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate a make rule for the generated TypeScript code.
+// See idl_gen_ts.cpp.
+extern std::string TSMakeRule(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate a make rule for the generated C++ header.
+// See idl_gen_cpp.cpp.
+extern std::string CPPMakeRule(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate a make rule for the generated Dart code
+// see idl_gen_dart.cpp
+extern std::string DartMakeRule(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate a make rule for the generated Rust code.
+// See idl_gen_rust.cpp.
+extern std::string RustMakeRule(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate a make rule for generated Java or C# files.
+// See code_generators.cpp.
+extern std::string JavaCSharpMakeRule(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate a make rule for the generated text (JSON) files.
+// See idl_gen_text.cpp.
+extern std::string TextMakeRule(const Parser &parser, const std::string &path,
+ const std::string &file_names);
+
+// Generate a make rule for the generated binary files.
+// See code_generators.cpp.
+extern std::string BinaryMakeRule(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate GRPC Cpp interfaces.
+// See idl_gen_grpc.cpp.
+bool GenerateCppGRPC(const Parser &parser, const std::string &path, const std::string &file_name);
+
+// Generate GRPC Go interfaces.
+// See idl_gen_grpc.cpp.
+bool GenerateGoGRPC(const Parser &parser, const std::string &path, const std::string &file_name);
+
+// Generate GRPC Java classes.
+// See idl_gen_grpc.cpp
+bool GenerateJavaGRPC(const Parser &parser, const std::string &path, const std::string &file_name);
+
+// Generate GRPC Python interfaces.
+// See idl_gen_grpc.cpp.
+bool GeneratePythonGRPC(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate GRPC Swift interfaces.
+// See idl_gen_grpc.cpp.
+extern bool GenerateSwiftGRPC(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+extern bool GenerateTSGRPC(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_IDL_H_
diff --git a/onert-micro/externals/flatbuffers/minireflect.h b/onert-micro/externals/flatbuffers/minireflect.h
new file mode 100644
index 000000000..8b733a4a5
--- /dev/null
+++ b/onert-micro/externals/flatbuffers/minireflect.h
@@ -0,0 +1,507 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2017 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLATBUFFERS_MINIREFLECT_H_
+#define FLATBUFFERS_MINIREFLECT_H_
+
+#include "flatbuffers/flatbuffers.h"
+#include "flatbuffers/util.h"
+
+namespace flatbuffers
+{
+
+// Utilities that can be used with the "mini reflection" tables present
+// in generated code with --reflect-types (only types) or --reflect-names
+// (also names).
+// This allows basic reflection functionality such as pretty-printing
+// that does not require the use of the schema parser or loading of binary
+// schema files at runtime (reflection.h).
+
+// For any of the functions below that take `const TypeTable *`, you pass
+// `FooTypeTable()` if the type of the root is `Foo`.
+
+// First, a generic iterator that can be used by multiple algorithms.
+
+struct IterationVisitor
+{
+ // These mark the scope of a table or struct.
+ virtual void StartSequence() {}
+ virtual void EndSequence() {}
+ // Called for each field regardless of whether it is present or not.
+ // If not present, val == nullptr. set_idx is the index of all set fields.
+ virtual void Field(size_t /*field_idx*/, size_t /*set_idx*/, ElementaryType /*type*/,
+ bool /*is_vector*/, const TypeTable * /*type_table*/, const char * /*name*/,
+ const uint8_t * /*val*/)
+ {
+ }
+ // Called for a value that is actually present, after a field, or as part
+ // of a vector.
+ virtual void UType(uint8_t, const char *) {}
+ virtual void Bool(bool) {}
+ virtual void Char(int8_t, const char *) {}
+ virtual void UChar(uint8_t, const char *) {}
+ virtual void Short(int16_t, const char *) {}
+ virtual void UShort(uint16_t, const char *) {}
+ virtual void Int(int32_t, const char *) {}
+ virtual void UInt(uint32_t, const char *) {}
+ virtual void Long(int64_t) {}
+ virtual void ULong(uint64_t) {}
+ virtual void Float(float) {}
+ virtual void Double(double) {}
+ virtual void String(const String *) {}
+ virtual void Unknown(const uint8_t *) {} // From a future version.
+ // These mark the scope of a vector.
+ virtual void StartVector() {}
+ virtual void EndVector() {}
+ virtual void Element(size_t /*i*/, ElementaryType /*type*/, const TypeTable * /*type_table*/,
+ const uint8_t * /*val*/)
+ {
+ }
+ virtual ~IterationVisitor() {}
+};
+
+inline size_t InlineSize(ElementaryType type, const TypeTable *type_table)
+{
+ switch (type)
+ {
+ case ET_UTYPE:
+ case ET_BOOL:
+ case ET_CHAR:
+ case ET_UCHAR:
+ return 1;
+ case ET_SHORT:
+ case ET_USHORT:
+ return 2;
+ case ET_INT:
+ case ET_UINT:
+ case ET_FLOAT:
+ case ET_STRING:
+ return 4;
+ case ET_LONG:
+ case ET_ULONG:
+ case ET_DOUBLE:
+ return 8;
+ case ET_SEQUENCE:
+ switch (type_table->st)
+ {
+ case ST_TABLE:
+ case ST_UNION:
+ return 4;
+ case ST_STRUCT:
+ return static_cast<size_t>(type_table->values[type_table->num_elems]);
+ default:
+ FLATBUFFERS_ASSERT(false);
+ return 1;
+ }
+ default:
+ FLATBUFFERS_ASSERT(false);
+ return 1;
+ }
+}
+
+inline int64_t LookupEnum(int64_t enum_val, const int64_t *values, size_t num_values)
+{
+ if (!values)
+ return enum_val;
+ for (size_t i = 0; i < num_values; i++)
+ {
+ if (enum_val == values[i])
+ return static_cast<int64_t>(i);
+ }
+ return -1; // Unknown enum value.
+}
+
+template <typename T> const char *EnumName(T tval, const TypeTable *type_table)
+{
+ if (!type_table || !type_table->names)
+ return nullptr;
+ auto i = LookupEnum(static_cast<int64_t>(tval), type_table->values, type_table->num_elems);
+ if (i >= 0 && i < static_cast<int64_t>(type_table->num_elems))
+ {
+ return type_table->names[i];
+ }
+ return nullptr;
+}
+
+void IterateObject(const uint8_t *obj, const TypeTable *type_table, IterationVisitor *visitor);
+
+inline void IterateValue(ElementaryType type, const uint8_t *val, const TypeTable *type_table,
+ const uint8_t *prev_val, soffset_t vector_index, IterationVisitor *visitor)
+{
+ switch (type)
+ {
+ case ET_UTYPE:
+ {
+ auto tval = ReadScalar<uint8_t>(val);
+ visitor->UType(tval, EnumName(tval, type_table));
+ break;
+ }
+ case ET_BOOL:
+ {
+ visitor->Bool(ReadScalar<uint8_t>(val) != 0);
+ break;
+ }
+ case ET_CHAR:
+ {
+ auto tval = ReadScalar<int8_t>(val);
+ visitor->Char(tval, EnumName(tval, type_table));
+ break;
+ }
+ case ET_UCHAR:
+ {
+ auto tval = ReadScalar<uint8_t>(val);
+ visitor->UChar(tval, EnumName(tval, type_table));
+ break;
+ }
+ case ET_SHORT:
+ {
+ auto tval = ReadScalar<int16_t>(val);
+ visitor->Short(tval, EnumName(tval, type_table));
+ break;
+ }
+ case ET_USHORT:
+ {
+ auto tval = ReadScalar<uint16_t>(val);
+ visitor->UShort(tval, EnumName(tval, type_table));
+ break;
+ }
+ case ET_INT:
+ {
+ auto tval = ReadScalar<int32_t>(val);
+ visitor->Int(tval, EnumName(tval, type_table));
+ break;
+ }
+ case ET_UINT:
+ {
+ auto tval = ReadScalar<uint32_t>(val);
+ visitor->UInt(tval, EnumName(tval, type_table));
+ break;
+ }
+ case ET_LONG:
+ {
+ visitor->Long(ReadScalar<int64_t>(val));
+ break;
+ }
+ case ET_ULONG:
+ {
+ visitor->ULong(ReadScalar<uint64_t>(val));
+ break;
+ }
+ case ET_FLOAT:
+ {
+ visitor->Float(ReadScalar<float>(val));
+ break;
+ }
+ case ET_DOUBLE:
+ {
+ visitor->Double(ReadScalar<double>(val));
+ break;
+ }
+ case ET_STRING:
+ {
+ val += ReadScalar<uoffset_t>(val);
+ visitor->String(reinterpret_cast<const String *>(val));
+ break;
+ }
+ case ET_SEQUENCE:
+ {
+ switch (type_table->st)
+ {
+ case ST_TABLE:
+ val += ReadScalar<uoffset_t>(val);
+ IterateObject(val, type_table, visitor);
+ break;
+ case ST_STRUCT:
+ IterateObject(val, type_table, visitor);
+ break;
+ case ST_UNION:
+ {
+ val += ReadScalar<uoffset_t>(val);
+ FLATBUFFERS_ASSERT(prev_val);
+ auto union_type = *prev_val; // Always a uint8_t.
+ if (vector_index >= 0)
+ {
+ auto type_vec = reinterpret_cast<const Vector<uint8_t> *>(prev_val);
+ union_type = type_vec->Get(static_cast<uoffset_t>(vector_index));
+ }
+ auto type_code_idx = LookupEnum(union_type, type_table->values, type_table->num_elems);
+ if (type_code_idx >= 0 && type_code_idx < static_cast<int32_t>(type_table->num_elems))
+ {
+ auto type_code = type_table->type_codes[type_code_idx];
+ switch (type_code.base_type)
+ {
+ case ET_SEQUENCE:
+ {
+ auto ref = type_table->type_refs[type_code.sequence_ref]();
+ IterateObject(val, ref, visitor);
+ break;
+ }
+ case ET_STRING:
+ visitor->String(reinterpret_cast<const String *>(val));
+ break;
+ default:
+ visitor->Unknown(val);
+ }
+ }
+ else
+ {
+ visitor->Unknown(val);
+ }
+ break;
+ }
+ case ST_ENUM:
+ FLATBUFFERS_ASSERT(false);
+ break;
+ }
+ break;
+ }
+ default:
+ {
+ visitor->Unknown(val);
+ break;
+ }
+ }
+}
+
+inline void IterateObject(const uint8_t *obj, const TypeTable *type_table,
+ IterationVisitor *visitor)
+{
+ visitor->StartSequence();
+ const uint8_t *prev_val = nullptr;
+ size_t set_idx = 0;
+ size_t array_idx = 0;
+ for (size_t i = 0; i < type_table->num_elems; i++)
+ {
+ auto type_code = type_table->type_codes[i];
+ auto type = static_cast<ElementaryType>(type_code.base_type);
+ auto is_repeating = type_code.is_repeating != 0;
+ auto ref_idx = type_code.sequence_ref;
+ const TypeTable *ref = nullptr;
+ if (ref_idx >= 0)
+ {
+ ref = type_table->type_refs[ref_idx]();
+ }
+ auto name = type_table->names ? type_table->names[i] : nullptr;
+ const uint8_t *val = nullptr;
+ if (type_table->st == ST_TABLE)
+ {
+ val = reinterpret_cast<const Table *>(obj)->GetAddressOf(
+ FieldIndexToOffset(static_cast<voffset_t>(i)));
+ }
+ else
+ {
+ val = obj + type_table->values[i];
+ }
+ visitor->Field(i, set_idx, type, is_repeating, ref, name, val);
+ if (val)
+ {
+ set_idx++;
+ if (is_repeating)
+ {
+ auto elem_ptr = val;
+ size_t size = 0;
+ if (type_table->st == ST_TABLE)
+ {
+ // variable length vector
+ val += ReadScalar<uoffset_t>(val);
+ auto vec = reinterpret_cast<const Vector<uint8_t> *>(val);
+ elem_ptr = vec->Data();
+ size = vec->size();
+ }
+ else
+ {
+ // otherwise fixed size array
+ size = type_table->array_sizes[array_idx];
+ ++array_idx;
+ }
+ visitor->StartVector();
+ for (size_t j = 0; j < size; j++)
+ {
+ visitor->Element(j, type, ref, elem_ptr);
+ IterateValue(type, elem_ptr, ref, prev_val, static_cast<soffset_t>(j), visitor);
+ elem_ptr += InlineSize(type, ref);
+ }
+ visitor->EndVector();
+ }
+ else
+ {
+ IterateValue(type, val, ref, prev_val, -1, visitor);
+ }
+ }
+ prev_val = val;
+ }
+ visitor->EndSequence();
+}
+
+inline void IterateFlatBuffer(const uint8_t *buffer, const TypeTable *type_table,
+ IterationVisitor *callback)
+{
+ IterateObject(GetRoot<uint8_t>(buffer), type_table, callback);
+}
+
+// Outputting a Flatbuffer to a string. Tries to conform as close to JSON /
+// the output generated by idl_gen_text.cpp.
+
+struct ToStringVisitor : public IterationVisitor
+{
+ std::string s;
+ std::string d;
+ bool q;
+ std::string in;
+ size_t indent_level;
+ bool vector_delimited;
+ ToStringVisitor(std::string delimiter, bool quotes, std::string indent, bool vdelimited = true)
+ : d(delimiter), q(quotes), in(indent), indent_level(0), vector_delimited(vdelimited)
+ {
+ }
+ ToStringVisitor(std::string delimiter)
+ : d(delimiter), q(false), in(""), indent_level(0), vector_delimited(true)
+ {
+ }
+
+ void append_indent()
+ {
+ for (size_t i = 0; i < indent_level; i++)
+ {
+ s += in;
+ }
+ }
+
+ void StartSequence()
+ {
+ s += "{";
+ s += d;
+ indent_level++;
+ }
+ void EndSequence()
+ {
+ s += d;
+ indent_level--;
+ append_indent();
+ s += "}";
+ }
+ void Field(size_t /*field_idx*/, size_t set_idx, ElementaryType /*type*/, bool /*is_vector*/,
+ const TypeTable * /*type_table*/, const char *name, const uint8_t *val)
+ {
+ if (!val)
+ return;
+ if (set_idx)
+ {
+ s += ",";
+ s += d;
+ }
+ append_indent();
+ if (name)
+ {
+ if (q)
+ s += "\"";
+ s += name;
+ if (q)
+ s += "\"";
+ s += ": ";
+ }
+ }
+ template <typename T> void Named(T x, const char *name)
+ {
+ if (name)
+ {
+ if (q)
+ s += "\"";
+ s += name;
+ if (q)
+ s += "\"";
+ }
+ else
+ {
+ s += NumToString(x);
+ }
+ }
+ void UType(uint8_t x, const char *name) { Named(x, name); }
+ void Bool(bool x) { s += x ? "true" : "false"; }
+ void Char(int8_t x, const char *name) { Named(x, name); }
+ void UChar(uint8_t x, const char *name) { Named(x, name); }
+ void Short(int16_t x, const char *name) { Named(x, name); }
+ void UShort(uint16_t x, const char *name) { Named(x, name); }
+ void Int(int32_t x, const char *name) { Named(x, name); }
+ void UInt(uint32_t x, const char *name) { Named(x, name); }
+ void Long(int64_t x) { s += NumToString(x); }
+ void ULong(uint64_t x) { s += NumToString(x); }
+ void Float(float x) { s += NumToString(x); }
+ void Double(double x) { s += NumToString(x); }
+ void String(const struct String *str)
+ {
+ EscapeString(str->c_str(), str->size(), &s, true, false);
+ }
+ void Unknown(const uint8_t *) { s += "(?)"; }
+ void StartVector()
+ {
+ s += "[";
+ if (vector_delimited)
+ {
+ s += d;
+ indent_level++;
+ append_indent();
+ }
+ else
+ {
+ s += " ";
+ }
+ }
+ void EndVector()
+ {
+ if (vector_delimited)
+ {
+ s += d;
+ indent_level--;
+ append_indent();
+ }
+ else
+ {
+ s += " ";
+ }
+ s += "]";
+ }
+ void Element(size_t i, ElementaryType /*type*/, const TypeTable * /*type_table*/,
+ const uint8_t * /*val*/)
+ {
+ if (i)
+ {
+ s += ",";
+ if (vector_delimited)
+ {
+ s += d;
+ append_indent();
+ }
+ else
+ {
+ s += " ";
+ }
+ }
+ }
+};
+
+inline std::string FlatBufferToString(const uint8_t *buffer, const TypeTable *type_table,
+ bool multi_line = false, bool vector_delimited = true)
+{
+ ToStringVisitor tostring_visitor(multi_line ? "\n" : " ", false, "", vector_delimited);
+ IterateFlatBuffer(buffer, type_table, &tostring_visitor);
+ return tostring_visitor.s;
+}
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_MINIREFLECT_H_
diff --git a/onert-micro/externals/flatbuffers/pch/flatc_pch.h b/onert-micro/externals/flatbuffers/pch/flatc_pch.h
new file mode 100644
index 000000000..988fcf371
--- /dev/null
+++ b/onert-micro/externals/flatbuffers/pch/flatc_pch.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2017 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLATBUFFERS_FLATC_PCH_H_
+#define FLATBUFFERS_FLATC_PCH_H_
+
+// stl
+#include <cmath>
+#include <sstream>
+#include <cassert>
+#include <unordered_set>
+#include <unordered_map>
+#include <iostream>
+#include <functional>
+#include <set>
+#include <iterator>
+#include <tuple>
+
+// flatbuffers
+#include "flatbuffers/pch/pch.h"
+#include "flatbuffers/code_generators.h"
+#include "flatbuffers/flatbuffers.h"
+#include "flatbuffers/flexbuffers.h"
+#include "flatbuffers/idl.h"
+
+#endif // FLATBUFFERS_FLATC_PCH_H_
diff --git a/onert-micro/externals/flatbuffers/pch/pch.h b/onert-micro/externals/flatbuffers/pch/pch.h
new file mode 100644
index 000000000..0e7886fb4
--- /dev/null
+++ b/onert-micro/externals/flatbuffers/pch/pch.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2017 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLATBUFFERS_PCH_H_
+#define FLATBUFFERS_PCH_H_
+
+// stl
+#include <cstdint>
+#include <cstring>
+#include <algorithm>
+#include <list>
+#include <string>
+#include <utility>
+#include <iomanip>
+#include <map>
+#include <memory>
+#include <limits>
+#include <stack>
+#include <vector>
+#include <type_traits>
+
+// flatbuffers
+#include "flatbuffers/util.h"
+
+#endif // FLATBUFFERS_PCH_H_
diff --git a/onert-micro/externals/flatbuffers/reflection.h b/onert-micro/externals/flatbuffers/reflection.h
new file mode 100644
index 000000000..8e2b155f7
--- /dev/null
+++ b/onert-micro/externals/flatbuffers/reflection.h
@@ -0,0 +1,520 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2015 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLATBUFFERS_REFLECTION_H_
+#define FLATBUFFERS_REFLECTION_H_
+
+// This is somewhat of a circular dependency because flatc (and thus this
+// file) is needed to generate this header in the first place.
+// Should normally not be a problem since it can be generated by the
+// previous version of flatc whenever this code needs to change.
+// See reflection/generate_code.sh
+#include "flatbuffers/reflection_generated.h"
+
+// Helper functionality for reflection.
+
+namespace flatbuffers
+{
+
+// ------------------------- GETTERS -------------------------
+
+inline bool IsScalar(reflection::BaseType t)
+{
+ return t >= reflection::UType && t <= reflection::Double;
+}
+inline bool IsInteger(reflection::BaseType t)
+{
+ return t >= reflection::UType && t <= reflection::ULong;
+}
+inline bool IsFloat(reflection::BaseType t)
+{
+ return t == reflection::Float || t == reflection::Double;
+}
+inline bool IsLong(reflection::BaseType t)
+{
+ return t == reflection::Long || t == reflection::ULong;
+}
+
+// Size of a basic type, don't use with structs.
+inline size_t GetTypeSize(reflection::BaseType base_type)
+{
+ // This needs to correspond to the BaseType enum.
+ static size_t sizes[] = {
+ 0, // None
+ 1, // UType
+ 1, // Bool
+ 1, // Byte
+ 1, // UByte
+ 2, // Short
+ 2, // UShort
+ 4, // Int
+ 4, // UInt
+ 8, // Long
+ 8, // ULong
+ 4, // Float
+ 8, // Double
+ 4, // String
+ 4, // Vector
+ 4, // Obj
+ 4, // Union
+ 0, // Array. Only used in structs. 0 was chosen to prevent out-of-bounds
+ // errors.
+
+ 0 // MaxBaseType. This must be kept the last entry in this array.
+ };
+ static_assert(sizeof(sizes) / sizeof(size_t) == reflection::MaxBaseType + 1,
+ "Size of sizes[] array does not match the count of BaseType "
+ "enum values.");
+ return sizes[base_type];
+}
+
+// Same as above, but now correctly returns the size of a struct if
+// the field (or vector element) is a struct.
+inline size_t GetTypeSizeInline(reflection::BaseType base_type, int type_index,
+ const reflection::Schema &schema)
+{
+ if (base_type == reflection::Obj && schema.objects()->Get(type_index)->is_struct())
+ {
+ return schema.objects()->Get(type_index)->bytesize();
+ }
+ else
+ {
+ return GetTypeSize(base_type);
+ }
+}
+
+// Get the root, regardless of what type it is.
+inline Table *GetAnyRoot(uint8_t *flatbuf) { return GetMutableRoot<Table>(flatbuf); }
+inline const Table *GetAnyRoot(const uint8_t *flatbuf) { return GetRoot<Table>(flatbuf); }
+
+// Get a field's default, if you know it's an integer, and its exact type.
+template <typename T> T GetFieldDefaultI(const reflection::Field &field)
+{
+ FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
+ return static_cast<T>(field.default_integer());
+}
+
+// Get a field's default, if you know it's floating point and its exact type.
+template <typename T> T GetFieldDefaultF(const reflection::Field &field)
+{
+ FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
+ return static_cast<T>(field.default_real());
+}
+
+// Get a field, if you know it's an integer, and its exact type.
+template <typename T> T GetFieldI(const Table &table, const reflection::Field &field)
+{
+ FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
+ return table.GetField<T>(field.offset(), static_cast<T>(field.default_integer()));
+}
+
+// Get a field, if you know it's floating point and its exact type.
+template <typename T> T GetFieldF(const Table &table, const reflection::Field &field)
+{
+ FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
+ return table.GetField<T>(field.offset(), static_cast<T>(field.default_real()));
+}
+
+// Get a field, if you know it's a string.
+inline const String *GetFieldS(const Table &table, const reflection::Field &field)
+{
+ FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::String);
+ return table.GetPointer<const String *>(field.offset());
+}
+
+// Get a field, if you know it's a vector.
+template <typename T> Vector<T> *GetFieldV(const Table &table, const reflection::Field &field)
+{
+ FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Vector &&
+ sizeof(T) == GetTypeSize(field.type()->element()));
+ return table.GetPointer<Vector<T> *>(field.offset());
+}
+
+// Get a field, if you know it's a vector, generically.
+// To actually access elements, use the return value together with
+// field.type()->element() in any of GetAnyVectorElemI below etc.
+inline VectorOfAny *GetFieldAnyV(const Table &table, const reflection::Field &field)
+{
+ return table.GetPointer<VectorOfAny *>(field.offset());
+}
+
+// Get a field, if you know it's a table.
+inline Table *GetFieldT(const Table &table, const reflection::Field &field)
+{
+ FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Obj ||
+ field.type()->base_type() == reflection::Union);
+ return table.GetPointer<Table *>(field.offset());
+}
+
+// Get a field, if you know it's a struct.
+inline const Struct *GetFieldStruct(const Table &table, const reflection::Field &field)
+{
+ // TODO: This does NOT check if the field is a table or struct, but we'd need
+ // access to the schema to check the is_struct flag.
+ FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Obj);
+ return table.GetStruct<const Struct *>(field.offset());
+}
+
+// Get a structure's field, if you know it's a struct.
+inline const Struct *GetFieldStruct(const Struct &structure, const reflection::Field &field)
+{
+ FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Obj);
+ return structure.GetStruct<const Struct *>(field.offset());
+}
+
+// Raw helper functions used below: get any value in memory as a 64bit int, a
+// double or a string.
+// All scalars get static_cast to an int64_t, strings use strtoull, every other
+// data type returns 0.
+int64_t GetAnyValueI(reflection::BaseType type, const uint8_t *data);
+// All scalars static cast to double, strings use strtod, every other data
+// type is 0.0.
+double GetAnyValueF(reflection::BaseType type, const uint8_t *data);
+// All scalars converted using stringstream, strings as-is, and all other
+// data types provide some level of debug-pretty-printing.
+std::string GetAnyValueS(reflection::BaseType type, const uint8_t *data,
+ const reflection::Schema *schema, int type_index);
+
+// Get any table field as a 64bit int, regardless of what type it is.
+inline int64_t GetAnyFieldI(const Table &table, const reflection::Field &field)
+{
+ auto field_ptr = table.GetAddressOf(field.offset());
+ return field_ptr ? GetAnyValueI(field.type()->base_type(), field_ptr) : field.default_integer();
+}
+
+// Get any table field as a double, regardless of what type it is.
+inline double GetAnyFieldF(const Table &table, const reflection::Field &field)
+{
+ auto field_ptr = table.GetAddressOf(field.offset());
+ return field_ptr ? GetAnyValueF(field.type()->base_type(), field_ptr) : field.default_real();
+}
+
+// Get any table field as a string, regardless of what type it is.
+// You may pass nullptr for the schema if you don't care to have fields that
+// are of table type pretty-printed.
+inline std::string GetAnyFieldS(const Table &table, const reflection::Field &field,
+ const reflection::Schema *schema)
+{
+ auto field_ptr = table.GetAddressOf(field.offset());
+ return field_ptr
+ ? GetAnyValueS(field.type()->base_type(), field_ptr, schema, field.type()->index())
+ : "";
+}
+
+// Get any struct field as a 64bit int, regardless of what type it is.
+inline int64_t GetAnyFieldI(const Struct &st, const reflection::Field &field)
+{
+ return GetAnyValueI(field.type()->base_type(), st.GetAddressOf(field.offset()));
+}
+
+// Get any struct field as a double, regardless of what type it is.
+inline double GetAnyFieldF(const Struct &st, const reflection::Field &field)
+{
+ return GetAnyValueF(field.type()->base_type(), st.GetAddressOf(field.offset()));
+}
+
+// Get any struct field as a string, regardless of what type it is.
+inline std::string GetAnyFieldS(const Struct &st, const reflection::Field &field)
+{
+ return GetAnyValueS(field.type()->base_type(), st.GetAddressOf(field.offset()), nullptr, -1);
+}
+
+// Get any vector element as a 64bit int, regardless of what type it is.
+inline int64_t GetAnyVectorElemI(const VectorOfAny *vec, reflection::BaseType elem_type, size_t i)
+{
+ return GetAnyValueI(elem_type, vec->Data() + GetTypeSize(elem_type) * i);
+}
+
+// Get any vector element as a double, regardless of what type it is.
+inline double GetAnyVectorElemF(const VectorOfAny *vec, reflection::BaseType elem_type, size_t i)
+{
+ return GetAnyValueF(elem_type, vec->Data() + GetTypeSize(elem_type) * i);
+}
+
+// Get any vector element as a string, regardless of what type it is.
+inline std::string GetAnyVectorElemS(const VectorOfAny *vec, reflection::BaseType elem_type,
+ size_t i)
+{
+ return GetAnyValueS(elem_type, vec->Data() + GetTypeSize(elem_type) * i, nullptr, -1);
+}
+
+// Get a vector element that's a table/string/vector from a generic vector.
+// Pass Table/String/VectorOfAny as template parameter.
+// Warning: does no typechecking.
+template <typename T> T *GetAnyVectorElemPointer(const VectorOfAny *vec, size_t i)
+{
+ auto elem_ptr = vec->Data() + sizeof(uoffset_t) * i;
+ return reinterpret_cast<T *>(elem_ptr + ReadScalar<uoffset_t>(elem_ptr));
+}
+
+// Get the inline-address of a vector element. Useful for Structs (pass Struct
+// as template arg), or being able to address a range of scalars in-line.
+// Get elem_size from GetTypeSizeInline().
+// Note: little-endian data on all platforms, use EndianScalar() instead of
+// raw pointer access with scalars).
+template <typename T>
+T *GetAnyVectorElemAddressOf(const VectorOfAny *vec, size_t i, size_t elem_size)
+{
+ return reinterpret_cast<T *>(vec->Data() + elem_size * i);
+}
+
+// Similarly, for elements of tables.
+template <typename T> T *GetAnyFieldAddressOf(const Table &table, const reflection::Field &field)
+{
+ return reinterpret_cast<T *>(table.GetAddressOf(field.offset()));
+}
+
+// Similarly, for elements of structs.
+template <typename T> T *GetAnyFieldAddressOf(const Struct &st, const reflection::Field &field)
+{
+ return reinterpret_cast<T *>(st.GetAddressOf(field.offset()));
+}
+
+// ------------------------- SETTERS -------------------------
+
+// Set any scalar field, if you know its exact type.
+template <typename T> bool SetField(Table *table, const reflection::Field &field, T val)
+{
+ reflection::BaseType type = field.type()->base_type();
+ if (!IsScalar(type))
+ {
+ return false;
+ }
+ FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(type));
+ T def;
+ if (IsInteger(type))
+ {
+ def = GetFieldDefaultI<T>(field);
+ }
+ else
+ {
+ FLATBUFFERS_ASSERT(IsFloat(type));
+ def = GetFieldDefaultF<T>(field);
+ }
+ return table->SetField(field.offset(), val, def);
+}
+
+// Raw helper functions used below: set any value in memory as a 64bit int, a
+// double or a string.
+// These work for all scalar values, but do nothing for other data types.
+// To set a string, see SetString below.
+void SetAnyValueI(reflection::BaseType type, uint8_t *data, int64_t val);
+void SetAnyValueF(reflection::BaseType type, uint8_t *data, double val);
+void SetAnyValueS(reflection::BaseType type, uint8_t *data, const char *val);
+
+// Set any table field as a 64bit int, regardless of type what it is.
+inline bool SetAnyFieldI(Table *table, const reflection::Field &field, int64_t val)
+{
+ auto field_ptr = table->GetAddressOf(field.offset());
+ if (!field_ptr)
+ return val == GetFieldDefaultI<int64_t>(field);
+ SetAnyValueI(field.type()->base_type(), field_ptr, val);
+ return true;
+}
+
+// Set any table field as a double, regardless of what type it is.
+inline bool SetAnyFieldF(Table *table, const reflection::Field &field, double val)
+{
+ auto field_ptr = table->GetAddressOf(field.offset());
+ if (!field_ptr)
+ return val == GetFieldDefaultF<double>(field);
+ SetAnyValueF(field.type()->base_type(), field_ptr, val);
+ return true;
+}
+
+// Set any table field as a string, regardless of what type it is.
+inline bool SetAnyFieldS(Table *table, const reflection::Field &field, const char *val)
+{
+ auto field_ptr = table->GetAddressOf(field.offset());
+ if (!field_ptr)
+ return false;
+ SetAnyValueS(field.type()->base_type(), field_ptr, val);
+ return true;
+}
+
+// Set any struct field as a 64bit int, regardless of type what it is.
+inline void SetAnyFieldI(Struct *st, const reflection::Field &field, int64_t val)
+{
+ SetAnyValueI(field.type()->base_type(), st->GetAddressOf(field.offset()), val);
+}
+
+// Set any struct field as a double, regardless of type what it is.
+inline void SetAnyFieldF(Struct *st, const reflection::Field &field, double val)
+{
+ SetAnyValueF(field.type()->base_type(), st->GetAddressOf(field.offset()), val);
+}
+
+// Set any struct field as a string, regardless of type what it is.
+inline void SetAnyFieldS(Struct *st, const reflection::Field &field, const char *val)
+{
+ SetAnyValueS(field.type()->base_type(), st->GetAddressOf(field.offset()), val);
+}
+
+// Set any vector element as a 64bit int, regardless of type what it is.
+inline void SetAnyVectorElemI(VectorOfAny *vec, reflection::BaseType elem_type, size_t i,
+ int64_t val)
+{
+ SetAnyValueI(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
+}
+
+// Set any vector element as a double, regardless of type what it is.
+inline void SetAnyVectorElemF(VectorOfAny *vec, reflection::BaseType elem_type, size_t i,
+ double val)
+{
+ SetAnyValueF(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
+}
+
+// Set any vector element as a string, regardless of type what it is.
+inline void SetAnyVectorElemS(VectorOfAny *vec, reflection::BaseType elem_type, size_t i,
+ const char *val)
+{
+ SetAnyValueS(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
+}
+
+// ------------------------- RESIZING SETTERS -------------------------
+
+// "smart" pointer for use with resizing vectors: turns a pointer inside
+// a vector into a relative offset, such that it is not affected by resizes.
+template <typename T, typename U> class pointer_inside_vector
+{
+public:
+ pointer_inside_vector(T *ptr, std::vector<U> &vec)
+ : offset_(reinterpret_cast<uint8_t *>(ptr) -
+ reinterpret_cast<uint8_t *>(flatbuffers::vector_data(vec))),
+ vec_(vec)
+ {
+ }
+
+ T *operator*() const
+ {
+ return reinterpret_cast<T *>(reinterpret_cast<uint8_t *>(flatbuffers::vector_data(vec_)) +
+ offset_);
+ }
+ T *operator->() const { return operator*(); }
+
+private:
+ size_t offset_;
+ std::vector<U> &vec_;
+};
+
+// Helper to create the above easily without specifying template args.
+template <typename T, typename U> pointer_inside_vector<T, U> piv(T *ptr, std::vector<U> &vec)
+{
+ return pointer_inside_vector<T, U>(ptr, vec);
+}
+
+inline const char *UnionTypeFieldSuffix() { return "_type"; }
+
+// Helper to figure out the actual table type a union refers to.
+inline const reflection::Object &GetUnionType(const reflection::Schema &schema,
+ const reflection::Object &parent,
+ const reflection::Field &unionfield,
+ const Table &table)
+{
+ auto enumdef = schema.enums()->Get(unionfield.type()->index());
+ // TODO: this is clumsy and slow, but no other way to find it?
+ auto type_field =
+ parent.fields()->LookupByKey((unionfield.name()->str() + UnionTypeFieldSuffix()).c_str());
+ FLATBUFFERS_ASSERT(type_field);
+ auto union_type = GetFieldI<uint8_t>(table, *type_field);
+ auto enumval = enumdef->values()->LookupByKey(union_type);
+ return *enumval->object();
+}
+
+// Changes the contents of a string inside a FlatBuffer. FlatBuffer must
+// live inside a std::vector so we can resize the buffer if needed.
+// "str" must live inside "flatbuf" and may be invalidated after this call.
+// If your FlatBuffer's root table is not the schema's root table, you should
+// pass in your root_table type as well.
+void SetString(const reflection::Schema &schema, const std::string &val, const String *str,
+ std::vector<uint8_t> *flatbuf, const reflection::Object *root_table = nullptr);
+
+// Resizes a flatbuffers::Vector inside a FlatBuffer. FlatBuffer must
+// live inside a std::vector so we can resize the buffer if needed.
+// "vec" must live inside "flatbuf" and may be invalidated after this call.
+// If your FlatBuffer's root table is not the schema's root table, you should
+// pass in your root_table type as well.
+uint8_t *ResizeAnyVector(const reflection::Schema &schema, uoffset_t newsize,
+ const VectorOfAny *vec, uoffset_t num_elems, uoffset_t elem_size,
+ std::vector<uint8_t> *flatbuf,
+ const reflection::Object *root_table = nullptr);
+
+template <typename T>
+void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val, const Vector<T> *vec,
+ std::vector<uint8_t> *flatbuf, const reflection::Object *root_table = nullptr)
+{
+ auto delta_elem = static_cast<int>(newsize) - static_cast<int>(vec->size());
+ auto newelems =
+ ResizeAnyVector(schema, newsize, reinterpret_cast<const VectorOfAny *>(vec), vec->size(),
+ static_cast<uoffset_t>(sizeof(T)), flatbuf, root_table);
+ // Set new elements to "val".
+ for (int i = 0; i < delta_elem; i++)
+ {
+ auto loc = newelems + i * sizeof(T);
+ auto is_scalar = flatbuffers::is_scalar<T>::value;
+ if (is_scalar)
+ {
+ WriteScalar(loc, val);
+ }
+ else
+ { // struct
+ *reinterpret_cast<T *>(loc) = val;
+ }
+ }
+}
+
+// Adds any new data (in the form of a new FlatBuffer) to an existing
+// FlatBuffer. This can be used when any of the above methods are not
+// sufficient, in particular for adding new tables and new fields.
+// This is potentially slightly less efficient than a FlatBuffer constructed
+// in one piece, since the new FlatBuffer doesn't share any vtables with the
+// existing one.
+// The return value can now be set using Vector::MutateOffset or SetFieldT
+// below.
+const uint8_t *AddFlatBuffer(std::vector<uint8_t> &flatbuf, const uint8_t *newbuf, size_t newlen);
+
+inline bool SetFieldT(Table *table, const reflection::Field &field, const uint8_t *val)
+{
+ FLATBUFFERS_ASSERT(sizeof(uoffset_t) == GetTypeSize(field.type()->base_type()));
+ return table->SetPointer(field.offset(), val);
+}
+
+// ------------------------- COPYING -------------------------
+
+// Generic copying of tables from a FlatBuffer into a FlatBuffer builder.
+// Can be used to do any kind of merging/selecting you may want to do out
+// of existing buffers. Also useful to reconstruct a whole buffer if the
+// above resizing functionality has introduced garbage in a buffer you want
+// to remove.
+// Note: this does not deal with DAGs correctly. If the table passed forms a
+// DAG, the copy will be a tree instead (with duplicates). Strings can be
+// shared however, by passing true for use_string_pooling.
+
+Offset<const Table *> CopyTable(FlatBufferBuilder &fbb, const reflection::Schema &schema,
+ const reflection::Object &objectdef, const Table &table,
+ bool use_string_pooling = false);
+
+// Verifies the provided flatbuffer using reflection.
+// root should point to the root type for this flatbuffer.
+// buf should point to the start of flatbuffer data.
+// length specifies the size of the flatbuffer data.
+bool Verify(const reflection::Schema &schema, const reflection::Object &root, const uint8_t *buf,
+ size_t length, uoffset_t max_depth = 64, uoffset_t max_tables = 1000000);
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_REFLECTION_H_
diff --git a/onert-micro/externals/flatbuffers/reflection_generated.h b/onert-micro/externals/flatbuffers/reflection_generated.h
new file mode 100644
index 000000000..9c57dd1f3
--- /dev/null
+++ b/onert-micro/externals/flatbuffers/reflection_generated.h
@@ -0,0 +1,1257 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2017 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// automatically generated by the FlatBuffers compiler, do not modify
+
+#ifndef FLATBUFFERS_GENERATED_REFLECTION_REFLECTION_H_
+#define FLATBUFFERS_GENERATED_REFLECTION_REFLECTION_H_
+
+#include "flatbuffers/flatbuffers.h"
+
+namespace reflection
+{
+
+struct Type;
+struct TypeBuilder;
+
+struct KeyValue;
+struct KeyValueBuilder;
+
+struct EnumVal;
+struct EnumValBuilder;
+
+struct Enum;
+struct EnumBuilder;
+
+struct Field;
+struct FieldBuilder;
+
+struct Object;
+struct ObjectBuilder;
+
+struct RPCCall;
+struct RPCCallBuilder;
+
+struct Service;
+struct ServiceBuilder;
+
+struct Schema;
+struct SchemaBuilder;
+
+enum BaseType
+{
+ None = 0,
+ UType = 1,
+ Bool = 2,
+ Byte = 3,
+ UByte = 4,
+ Short = 5,
+ UShort = 6,
+ Int = 7,
+ UInt = 8,
+ Long = 9,
+ ULong = 10,
+ Float = 11,
+ Double = 12,
+ String = 13,
+ Vector = 14,
+ Obj = 15,
+ Union = 16,
+ Array = 17,
+ MaxBaseType = 18
+};
+
+inline const BaseType (&EnumValuesBaseType())[19]
+{
+ static const BaseType values[] = {None, UType, Bool, Byte, UByte, Short, UShort,
+ Int, UInt, Long, ULong, Float, Double, String,
+ Vector, Obj, Union, Array, MaxBaseType};
+ return values;
+}
+
+inline const char *const *EnumNamesBaseType()
+{
+ static const char *const names[20] = {"None", "UType", "Bool", "Byte", "UByte",
+ "Short", "UShort", "Int", "UInt", "Long",
+ "ULong", "Float", "Double", "String", "Vector",
+ "Obj", "Union", "Array", "MaxBaseType", nullptr};
+ return names;
+}
+
+inline const char *EnumNameBaseType(BaseType e)
+{
+ if (flatbuffers::IsOutRange(e, None, MaxBaseType))
+ return "";
+ const size_t index = static_cast<size_t>(e);
+ return EnumNamesBaseType()[index];
+}
+
+enum AdvancedFeatures
+{
+ AdvancedArrayFeatures = 1ULL,
+ AdvancedUnionFeatures = 2ULL,
+ OptionalScalars = 4ULL,
+ DefaultVectorsAndStrings = 8ULL
+};
+
+inline const AdvancedFeatures (&EnumValuesAdvancedFeatures())[4]
+{
+ static const AdvancedFeatures values[] = {AdvancedArrayFeatures, AdvancedUnionFeatures,
+ OptionalScalars, DefaultVectorsAndStrings};
+ return values;
+}
+
+inline const char *const *EnumNamesAdvancedFeatures()
+{
+ static const char *const names[9] = {"AdvancedArrayFeatures",
+ "AdvancedUnionFeatures",
+ "",
+ "OptionalScalars",
+ "",
+ "",
+ "",
+ "DefaultVectorsAndStrings",
+ nullptr};
+ return names;
+}
+
+inline const char *EnumNameAdvancedFeatures(AdvancedFeatures e)
+{
+ if (flatbuffers::IsOutRange(e, AdvancedArrayFeatures, DefaultVectorsAndStrings))
+ return "";
+ const size_t index = static_cast<size_t>(e) - static_cast<size_t>(AdvancedArrayFeatures);
+ return EnumNamesAdvancedFeatures()[index];
+}
+
+struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef TypeBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_BASE_TYPE = 4,
+ VT_ELEMENT = 6,
+ VT_INDEX = 8,
+ VT_FIXED_LENGTH = 10
+ };
+ reflection::BaseType base_type() const
+ {
+ return static_cast<reflection::BaseType>(GetField<int8_t>(VT_BASE_TYPE, 0));
+ }
+ reflection::BaseType element() const
+ {
+ return static_cast<reflection::BaseType>(GetField<int8_t>(VT_ELEMENT, 0));
+ }
+ int32_t index() const { return GetField<int32_t>(VT_INDEX, -1); }
+ uint16_t fixed_length() const { return GetField<uint16_t>(VT_FIXED_LENGTH, 0); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_BASE_TYPE) &&
+ VerifyField<int8_t>(verifier, VT_ELEMENT) && VerifyField<int32_t>(verifier, VT_INDEX) &&
+ VerifyField<uint16_t>(verifier, VT_FIXED_LENGTH) && verifier.EndTable();
+ }
+};
+
+struct TypeBuilder
+{
+ typedef Type Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_base_type(reflection::BaseType base_type)
+ {
+ fbb_.AddElement<int8_t>(Type::VT_BASE_TYPE, static_cast<int8_t>(base_type), 0);
+ }
+ void add_element(reflection::BaseType element)
+ {
+ fbb_.AddElement<int8_t>(Type::VT_ELEMENT, static_cast<int8_t>(element), 0);
+ }
+ void add_index(int32_t index) { fbb_.AddElement<int32_t>(Type::VT_INDEX, index, -1); }
+ void add_fixed_length(uint16_t fixed_length)
+ {
+ fbb_.AddElement<uint16_t>(Type::VT_FIXED_LENGTH, fixed_length, 0);
+ }
+ explicit TypeBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<Type> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Type>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Type> CreateType(flatbuffers::FlatBufferBuilder &_fbb,
+ reflection::BaseType base_type = reflection::None,
+ reflection::BaseType element = reflection::None,
+ int32_t index = -1, uint16_t fixed_length = 0)
+{
+ TypeBuilder builder_(_fbb);
+ builder_.add_index(index);
+ builder_.add_fixed_length(fixed_length);
+ builder_.add_element(element);
+ builder_.add_base_type(base_type);
+ return builder_.Finish();
+}
+
+struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef KeyValueBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_KEY = 4,
+ VT_VALUE = 6
+ };
+ const flatbuffers::String *key() const { return GetPointer<const flatbuffers::String *>(VT_KEY); }
+ bool KeyCompareLessThan(const KeyValue *o) const { return *key() < *o->key(); }
+ int KeyCompareWithValue(const char *val) const { return strcmp(key()->c_str(), val); }
+ const flatbuffers::String *value() const
+ {
+ return GetPointer<const flatbuffers::String *>(VT_VALUE);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffsetRequired(verifier, VT_KEY) &&
+ verifier.VerifyString(key()) && VerifyOffset(verifier, VT_VALUE) &&
+ verifier.VerifyString(value()) && verifier.EndTable();
+ }
+};
+
+struct KeyValueBuilder
+{
+ typedef KeyValue Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_key(flatbuffers::Offset<flatbuffers::String> key)
+ {
+ fbb_.AddOffset(KeyValue::VT_KEY, key);
+ }
+ void add_value(flatbuffers::Offset<flatbuffers::String> value)
+ {
+ fbb_.AddOffset(KeyValue::VT_VALUE, value);
+ }
+ explicit KeyValueBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<KeyValue> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<KeyValue>(end);
+ fbb_.Required(o, KeyValue::VT_KEY);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<KeyValue>
+CreateKeyValue(flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::String> key = 0,
+ flatbuffers::Offset<flatbuffers::String> value = 0)
+{
+ KeyValueBuilder builder_(_fbb);
+ builder_.add_value(value);
+ builder_.add_key(key);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<KeyValue> CreateKeyValueDirect(flatbuffers::FlatBufferBuilder &_fbb,
+ const char *key = nullptr,
+ const char *value = nullptr)
+{
+ auto key__ = key ? _fbb.CreateString(key) : 0;
+ auto value__ = value ? _fbb.CreateString(value) : 0;
+ return reflection::CreateKeyValue(_fbb, key__, value__);
+}
+
+struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef EnumValBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_NAME = 4,
+ VT_VALUE = 6,
+ VT_OBJECT = 8,
+ VT_UNION_TYPE = 10,
+ VT_DOCUMENTATION = 12
+ };
+ const flatbuffers::String *name() const
+ {
+ return GetPointer<const flatbuffers::String *>(VT_NAME);
+ }
+ int64_t value() const { return GetField<int64_t>(VT_VALUE, 0); }
+ bool KeyCompareLessThan(const EnumVal *o) const { return value() < o->value(); }
+ int KeyCompareWithValue(int64_t val) const
+ {
+ return static_cast<int>(value() > val) - static_cast<int>(value() < val);
+ }
+ const reflection::Object *object() const
+ {
+ return GetPointer<const reflection::Object *>(VT_OBJECT);
+ }
+ const reflection::Type *union_type() const
+ {
+ return GetPointer<const reflection::Type *>(VT_UNION_TYPE);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(
+ VT_DOCUMENTATION);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffsetRequired(verifier, VT_NAME) &&
+ verifier.VerifyString(name()) && VerifyField<int64_t>(verifier, VT_VALUE) &&
+ VerifyOffset(verifier, VT_OBJECT) && verifier.VerifyTable(object()) &&
+ VerifyOffset(verifier, VT_UNION_TYPE) && verifier.VerifyTable(union_type()) &&
+ VerifyOffset(verifier, VT_DOCUMENTATION) && verifier.VerifyVector(documentation()) &&
+ verifier.VerifyVectorOfStrings(documentation()) && verifier.EndTable();
+ }
+};
+
+struct EnumValBuilder
+{
+ typedef EnumVal Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_name(flatbuffers::Offset<flatbuffers::String> name)
+ {
+ fbb_.AddOffset(EnumVal::VT_NAME, name);
+ }
+ void add_value(int64_t value) { fbb_.AddElement<int64_t>(EnumVal::VT_VALUE, value, 0); }
+ void add_object(flatbuffers::Offset<reflection::Object> object)
+ {
+ fbb_.AddOffset(EnumVal::VT_OBJECT, object);
+ }
+ void add_union_type(flatbuffers::Offset<reflection::Type> union_type)
+ {
+ fbb_.AddOffset(EnumVal::VT_UNION_TYPE, union_type);
+ }
+ void add_documentation(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>>
+ documentation)
+ {
+ fbb_.AddOffset(EnumVal::VT_DOCUMENTATION, documentation);
+ }
+ explicit EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<EnumVal> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<EnumVal>(end);
+ fbb_.Required(o, EnumVal::VT_NAME);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<EnumVal> CreateEnumVal(
+ flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::Offset<flatbuffers::String> name = 0,
+ int64_t value = 0, flatbuffers::Offset<reflection::Object> object = 0,
+ flatbuffers::Offset<reflection::Type> union_type = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation =
+ 0)
+{
+ EnumValBuilder builder_(_fbb);
+ builder_.add_value(value);
+ builder_.add_documentation(documentation);
+ builder_.add_union_type(union_type);
+ builder_.add_object(object);
+ builder_.add_name(name);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<EnumVal> CreateEnumValDirect(
+ flatbuffers::FlatBufferBuilder &_fbb, const char *name = nullptr, int64_t value = 0,
+ flatbuffers::Offset<reflection::Object> object = 0,
+ flatbuffers::Offset<reflection::Type> union_type = 0,
+ const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr)
+{
+ auto name__ = name ? _fbb.CreateString(name) : 0;
+ auto documentation__ =
+ documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
+ return reflection::CreateEnumVal(_fbb, name__, value, object, union_type, documentation__);
+}
+
+struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef EnumBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_NAME = 4,
+ VT_VALUES = 6,
+ VT_IS_UNION = 8,
+ VT_UNDERLYING_TYPE = 10,
+ VT_ATTRIBUTES = 12,
+ VT_DOCUMENTATION = 14
+ };
+ const flatbuffers::String *name() const
+ {
+ return GetPointer<const flatbuffers::String *>(VT_NAME);
+ }
+ bool KeyCompareLessThan(const Enum *o) const { return *name() < *o->name(); }
+ int KeyCompareWithValue(const char *val) const { return strcmp(name()->c_str(), val); }
+ const flatbuffers::Vector<flatbuffers::Offset<reflection::EnumVal>> *values() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::EnumVal>> *>(
+ VT_VALUES);
+ }
+ bool is_union() const { return GetField<uint8_t>(VT_IS_UNION, 0) != 0; }
+ const reflection::Type *underlying_type() const
+ {
+ return GetPointer<const reflection::Type *>(VT_UNDERLYING_TYPE);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(
+ VT_ATTRIBUTES);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(
+ VT_DOCUMENTATION);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffsetRequired(verifier, VT_NAME) &&
+ verifier.VerifyString(name()) && VerifyOffsetRequired(verifier, VT_VALUES) &&
+ verifier.VerifyVector(values()) && verifier.VerifyVectorOfTables(values()) &&
+ VerifyField<uint8_t>(verifier, VT_IS_UNION) &&
+ VerifyOffsetRequired(verifier, VT_UNDERLYING_TYPE) &&
+ verifier.VerifyTable(underlying_type()) && VerifyOffset(verifier, VT_ATTRIBUTES) &&
+ verifier.VerifyVector(attributes()) && verifier.VerifyVectorOfTables(attributes()) &&
+ VerifyOffset(verifier, VT_DOCUMENTATION) && verifier.VerifyVector(documentation()) &&
+ verifier.VerifyVectorOfStrings(documentation()) && verifier.EndTable();
+ }
+};
+
+struct EnumBuilder
+{
+ typedef Enum Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_name(flatbuffers::Offset<flatbuffers::String> name)
+ {
+ fbb_.AddOffset(Enum::VT_NAME, name);
+ }
+ void add_values(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::EnumVal>>> values)
+ {
+ fbb_.AddOffset(Enum::VT_VALUES, values);
+ }
+ void add_is_union(bool is_union)
+ {
+ fbb_.AddElement<uint8_t>(Enum::VT_IS_UNION, static_cast<uint8_t>(is_union), 0);
+ }
+ void add_underlying_type(flatbuffers::Offset<reflection::Type> underlying_type)
+ {
+ fbb_.AddOffset(Enum::VT_UNDERLYING_TYPE, underlying_type);
+ }
+ void add_attributes(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes)
+ {
+ fbb_.AddOffset(Enum::VT_ATTRIBUTES, attributes);
+ }
+ void add_documentation(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>>
+ documentation)
+ {
+ fbb_.AddOffset(Enum::VT_DOCUMENTATION, documentation);
+ }
+ explicit EnumBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<Enum> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Enum>(end);
+ fbb_.Required(o, Enum::VT_NAME);
+ fbb_.Required(o, Enum::VT_VALUES);
+ fbb_.Required(o, Enum::VT_UNDERLYING_TYPE);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Enum> CreateEnum(
+ flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::Offset<flatbuffers::String> name = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::EnumVal>>> values = 0,
+ bool is_union = false, flatbuffers::Offset<reflection::Type> underlying_type = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes =
+ 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation =
+ 0)
+{
+ EnumBuilder builder_(_fbb);
+ builder_.add_documentation(documentation);
+ builder_.add_attributes(attributes);
+ builder_.add_underlying_type(underlying_type);
+ builder_.add_values(values);
+ builder_.add_name(name);
+ builder_.add_is_union(is_union);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<Enum> CreateEnumDirect(
+ flatbuffers::FlatBufferBuilder &_fbb, const char *name = nullptr,
+ std::vector<flatbuffers::Offset<reflection::EnumVal>> *values = nullptr, bool is_union = false,
+ flatbuffers::Offset<reflection::Type> underlying_type = 0,
+ std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
+ const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr)
+{
+ auto name__ = name ? _fbb.CreateString(name) : 0;
+ auto values__ = values ? _fbb.CreateVectorOfSortedTables<reflection::EnumVal>(values) : 0;
+ auto attributes__ =
+ attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
+ auto documentation__ =
+ documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
+ return reflection::CreateEnum(_fbb, name__, values__, is_union, underlying_type, attributes__,
+ documentation__);
+}
+
+struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef FieldBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_NAME = 4,
+ VT_TYPE = 6,
+ VT_ID = 8,
+ VT_OFFSET = 10,
+ VT_DEFAULT_INTEGER = 12,
+ VT_DEFAULT_REAL = 14,
+ VT_DEPRECATED = 16,
+ VT_REQUIRED = 18,
+ VT_KEY = 20,
+ VT_ATTRIBUTES = 22,
+ VT_DOCUMENTATION = 24,
+ VT_OPTIONAL = 26
+ };
+ const flatbuffers::String *name() const
+ {
+ return GetPointer<const flatbuffers::String *>(VT_NAME);
+ }
+ bool KeyCompareLessThan(const Field *o) const { return *name() < *o->name(); }
+ int KeyCompareWithValue(const char *val) const { return strcmp(name()->c_str(), val); }
+ const reflection::Type *type() const { return GetPointer<const reflection::Type *>(VT_TYPE); }
+ uint16_t id() const { return GetField<uint16_t>(VT_ID, 0); }
+ uint16_t offset() const { return GetField<uint16_t>(VT_OFFSET, 0); }
+ int64_t default_integer() const { return GetField<int64_t>(VT_DEFAULT_INTEGER, 0); }
+ double default_real() const { return GetField<double>(VT_DEFAULT_REAL, 0.0); }
+ bool deprecated() const { return GetField<uint8_t>(VT_DEPRECATED, 0) != 0; }
+ bool required() const { return GetField<uint8_t>(VT_REQUIRED, 0) != 0; }
+ bool key() const { return GetField<uint8_t>(VT_KEY, 0) != 0; }
+ const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(
+ VT_ATTRIBUTES);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(
+ VT_DOCUMENTATION);
+ }
+ bool optional() const { return GetField<uint8_t>(VT_OPTIONAL, 0) != 0; }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffsetRequired(verifier, VT_NAME) &&
+ verifier.VerifyString(name()) && VerifyOffsetRequired(verifier, VT_TYPE) &&
+ verifier.VerifyTable(type()) && VerifyField<uint16_t>(verifier, VT_ID) &&
+ VerifyField<uint16_t>(verifier, VT_OFFSET) &&
+ VerifyField<int64_t>(verifier, VT_DEFAULT_INTEGER) &&
+ VerifyField<double>(verifier, VT_DEFAULT_REAL) &&
+ VerifyField<uint8_t>(verifier, VT_DEPRECATED) &&
+ VerifyField<uint8_t>(verifier, VT_REQUIRED) && VerifyField<uint8_t>(verifier, VT_KEY) &&
+ VerifyOffset(verifier, VT_ATTRIBUTES) && verifier.VerifyVector(attributes()) &&
+ verifier.VerifyVectorOfTables(attributes()) &&
+ VerifyOffset(verifier, VT_DOCUMENTATION) && verifier.VerifyVector(documentation()) &&
+ verifier.VerifyVectorOfStrings(documentation()) &&
+ VerifyField<uint8_t>(verifier, VT_OPTIONAL) && verifier.EndTable();
+ }
+};
+
+struct FieldBuilder
+{
+ typedef Field Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_name(flatbuffers::Offset<flatbuffers::String> name)
+ {
+ fbb_.AddOffset(Field::VT_NAME, name);
+ }
+ void add_type(flatbuffers::Offset<reflection::Type> type)
+ {
+ fbb_.AddOffset(Field::VT_TYPE, type);
+ }
+ void add_id(uint16_t id) { fbb_.AddElement<uint16_t>(Field::VT_ID, id, 0); }
+ void add_offset(uint16_t offset) { fbb_.AddElement<uint16_t>(Field::VT_OFFSET, offset, 0); }
+ void add_default_integer(int64_t default_integer)
+ {
+ fbb_.AddElement<int64_t>(Field::VT_DEFAULT_INTEGER, default_integer, 0);
+ }
+ void add_default_real(double default_real)
+ {
+ fbb_.AddElement<double>(Field::VT_DEFAULT_REAL, default_real, 0.0);
+ }
+ void add_deprecated(bool deprecated)
+ {
+ fbb_.AddElement<uint8_t>(Field::VT_DEPRECATED, static_cast<uint8_t>(deprecated), 0);
+ }
+ void add_required(bool required)
+ {
+ fbb_.AddElement<uint8_t>(Field::VT_REQUIRED, static_cast<uint8_t>(required), 0);
+ }
+ void add_key(bool key) { fbb_.AddElement<uint8_t>(Field::VT_KEY, static_cast<uint8_t>(key), 0); }
+ void add_attributes(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes)
+ {
+ fbb_.AddOffset(Field::VT_ATTRIBUTES, attributes);
+ }
+ void add_documentation(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>>
+ documentation)
+ {
+ fbb_.AddOffset(Field::VT_DOCUMENTATION, documentation);
+ }
+ void add_optional(bool optional)
+ {
+ fbb_.AddElement<uint8_t>(Field::VT_OPTIONAL, static_cast<uint8_t>(optional), 0);
+ }
+ explicit FieldBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<Field> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Field>(end);
+ fbb_.Required(o, Field::VT_NAME);
+ fbb_.Required(o, Field::VT_TYPE);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Field> CreateField(
+ flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::Offset<flatbuffers::String> name = 0,
+ flatbuffers::Offset<reflection::Type> type = 0, uint16_t id = 0, uint16_t offset = 0,
+ int64_t default_integer = 0, double default_real = 0.0, bool deprecated = false,
+ bool required = false, bool key = false,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes =
+ 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation =
+ 0,
+ bool optional = false)
+{
+ FieldBuilder builder_(_fbb);
+ builder_.add_default_real(default_real);
+ builder_.add_default_integer(default_integer);
+ builder_.add_documentation(documentation);
+ builder_.add_attributes(attributes);
+ builder_.add_type(type);
+ builder_.add_name(name);
+ builder_.add_offset(offset);
+ builder_.add_id(id);
+ builder_.add_optional(optional);
+ builder_.add_key(key);
+ builder_.add_required(required);
+ builder_.add_deprecated(deprecated);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<Field> CreateFieldDirect(
+ flatbuffers::FlatBufferBuilder &_fbb, const char *name = nullptr,
+ flatbuffers::Offset<reflection::Type> type = 0, uint16_t id = 0, uint16_t offset = 0,
+ int64_t default_integer = 0, double default_real = 0.0, bool deprecated = false,
+ bool required = false, bool key = false,
+ std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
+ const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr,
+ bool optional = false)
+{
+ auto name__ = name ? _fbb.CreateString(name) : 0;
+ auto attributes__ =
+ attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
+ auto documentation__ =
+ documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
+ return reflection::CreateField(_fbb, name__, type, id, offset, default_integer, default_real,
+ deprecated, required, key, attributes__, documentation__,
+ optional);
+}
+
+struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef ObjectBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_NAME = 4,
+ VT_FIELDS = 6,
+ VT_IS_STRUCT = 8,
+ VT_MINALIGN = 10,
+ VT_BYTESIZE = 12,
+ VT_ATTRIBUTES = 14,
+ VT_DOCUMENTATION = 16
+ };
+ const flatbuffers::String *name() const
+ {
+ return GetPointer<const flatbuffers::String *>(VT_NAME);
+ }
+ bool KeyCompareLessThan(const Object *o) const { return *name() < *o->name(); }
+ int KeyCompareWithValue(const char *val) const { return strcmp(name()->c_str(), val); }
+ const flatbuffers::Vector<flatbuffers::Offset<reflection::Field>> *fields() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Field>> *>(
+ VT_FIELDS);
+ }
+ bool is_struct() const { return GetField<uint8_t>(VT_IS_STRUCT, 0) != 0; }
+ int32_t minalign() const { return GetField<int32_t>(VT_MINALIGN, 0); }
+ int32_t bytesize() const { return GetField<int32_t>(VT_BYTESIZE, 0); }
+ const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(
+ VT_ATTRIBUTES);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(
+ VT_DOCUMENTATION);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffsetRequired(verifier, VT_NAME) &&
+ verifier.VerifyString(name()) && VerifyOffsetRequired(verifier, VT_FIELDS) &&
+ verifier.VerifyVector(fields()) && verifier.VerifyVectorOfTables(fields()) &&
+ VerifyField<uint8_t>(verifier, VT_IS_STRUCT) &&
+ VerifyField<int32_t>(verifier, VT_MINALIGN) &&
+ VerifyField<int32_t>(verifier, VT_BYTESIZE) && VerifyOffset(verifier, VT_ATTRIBUTES) &&
+ verifier.VerifyVector(attributes()) && verifier.VerifyVectorOfTables(attributes()) &&
+ VerifyOffset(verifier, VT_DOCUMENTATION) && verifier.VerifyVector(documentation()) &&
+ verifier.VerifyVectorOfStrings(documentation()) && verifier.EndTable();
+ }
+};
+
+struct ObjectBuilder
+{
+ typedef Object Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_name(flatbuffers::Offset<flatbuffers::String> name)
+ {
+ fbb_.AddOffset(Object::VT_NAME, name);
+ }
+ void add_fields(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Field>>> fields)
+ {
+ fbb_.AddOffset(Object::VT_FIELDS, fields);
+ }
+ void add_is_struct(bool is_struct)
+ {
+ fbb_.AddElement<uint8_t>(Object::VT_IS_STRUCT, static_cast<uint8_t>(is_struct), 0);
+ }
+ void add_minalign(int32_t minalign)
+ {
+ fbb_.AddElement<int32_t>(Object::VT_MINALIGN, minalign, 0);
+ }
+ void add_bytesize(int32_t bytesize)
+ {
+ fbb_.AddElement<int32_t>(Object::VT_BYTESIZE, bytesize, 0);
+ }
+ void add_attributes(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes)
+ {
+ fbb_.AddOffset(Object::VT_ATTRIBUTES, attributes);
+ }
+ void add_documentation(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>>
+ documentation)
+ {
+ fbb_.AddOffset(Object::VT_DOCUMENTATION, documentation);
+ }
+ explicit ObjectBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<Object> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Object>(end);
+ fbb_.Required(o, Object::VT_NAME);
+ fbb_.Required(o, Object::VT_FIELDS);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Object> CreateObject(
+ flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::Offset<flatbuffers::String> name = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Field>>> fields = 0,
+ bool is_struct = false, int32_t minalign = 0, int32_t bytesize = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes =
+ 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation =
+ 0)
+{
+ ObjectBuilder builder_(_fbb);
+ builder_.add_documentation(documentation);
+ builder_.add_attributes(attributes);
+ builder_.add_bytesize(bytesize);
+ builder_.add_minalign(minalign);
+ builder_.add_fields(fields);
+ builder_.add_name(name);
+ builder_.add_is_struct(is_struct);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<Object> CreateObjectDirect(
+ flatbuffers::FlatBufferBuilder &_fbb, const char *name = nullptr,
+ std::vector<flatbuffers::Offset<reflection::Field>> *fields = nullptr, bool is_struct = false,
+ int32_t minalign = 0, int32_t bytesize = 0,
+ std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
+ const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr)
+{
+ auto name__ = name ? _fbb.CreateString(name) : 0;
+ auto fields__ = fields ? _fbb.CreateVectorOfSortedTables<reflection::Field>(fields) : 0;
+ auto attributes__ =
+ attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
+ auto documentation__ =
+ documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
+ return reflection::CreateObject(_fbb, name__, fields__, is_struct, minalign, bytesize,
+ attributes__, documentation__);
+}
+
+struct RPCCall FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef RPCCallBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_NAME = 4,
+ VT_REQUEST = 6,
+ VT_RESPONSE = 8,
+ VT_ATTRIBUTES = 10,
+ VT_DOCUMENTATION = 12
+ };
+ const flatbuffers::String *name() const
+ {
+ return GetPointer<const flatbuffers::String *>(VT_NAME);
+ }
+ bool KeyCompareLessThan(const RPCCall *o) const { return *name() < *o->name(); }
+ int KeyCompareWithValue(const char *val) const { return strcmp(name()->c_str(), val); }
+ const reflection::Object *request() const
+ {
+ return GetPointer<const reflection::Object *>(VT_REQUEST);
+ }
+ const reflection::Object *response() const
+ {
+ return GetPointer<const reflection::Object *>(VT_RESPONSE);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(
+ VT_ATTRIBUTES);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(
+ VT_DOCUMENTATION);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffsetRequired(verifier, VT_NAME) &&
+ verifier.VerifyString(name()) && VerifyOffsetRequired(verifier, VT_REQUEST) &&
+ verifier.VerifyTable(request()) && VerifyOffsetRequired(verifier, VT_RESPONSE) &&
+ verifier.VerifyTable(response()) && VerifyOffset(verifier, VT_ATTRIBUTES) &&
+ verifier.VerifyVector(attributes()) && verifier.VerifyVectorOfTables(attributes()) &&
+ VerifyOffset(verifier, VT_DOCUMENTATION) && verifier.VerifyVector(documentation()) &&
+ verifier.VerifyVectorOfStrings(documentation()) && verifier.EndTable();
+ }
+};
+
+struct RPCCallBuilder
+{
+ typedef RPCCall Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_name(flatbuffers::Offset<flatbuffers::String> name)
+ {
+ fbb_.AddOffset(RPCCall::VT_NAME, name);
+ }
+ void add_request(flatbuffers::Offset<reflection::Object> request)
+ {
+ fbb_.AddOffset(RPCCall::VT_REQUEST, request);
+ }
+ void add_response(flatbuffers::Offset<reflection::Object> response)
+ {
+ fbb_.AddOffset(RPCCall::VT_RESPONSE, response);
+ }
+ void add_attributes(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes)
+ {
+ fbb_.AddOffset(RPCCall::VT_ATTRIBUTES, attributes);
+ }
+ void add_documentation(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>>
+ documentation)
+ {
+ fbb_.AddOffset(RPCCall::VT_DOCUMENTATION, documentation);
+ }
+ explicit RPCCallBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<RPCCall> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<RPCCall>(end);
+ fbb_.Required(o, RPCCall::VT_NAME);
+ fbb_.Required(o, RPCCall::VT_REQUEST);
+ fbb_.Required(o, RPCCall::VT_RESPONSE);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<RPCCall> CreateRPCCall(
+ flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::Offset<flatbuffers::String> name = 0,
+ flatbuffers::Offset<reflection::Object> request = 0,
+ flatbuffers::Offset<reflection::Object> response = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes =
+ 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation =
+ 0)
+{
+ RPCCallBuilder builder_(_fbb);
+ builder_.add_documentation(documentation);
+ builder_.add_attributes(attributes);
+ builder_.add_response(response);
+ builder_.add_request(request);
+ builder_.add_name(name);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<RPCCall> CreateRPCCallDirect(
+ flatbuffers::FlatBufferBuilder &_fbb, const char *name = nullptr,
+ flatbuffers::Offset<reflection::Object> request = 0,
+ flatbuffers::Offset<reflection::Object> response = 0,
+ std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
+ const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr)
+{
+ auto name__ = name ? _fbb.CreateString(name) : 0;
+ auto attributes__ =
+ attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
+ auto documentation__ =
+ documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
+ return reflection::CreateRPCCall(_fbb, name__, request, response, attributes__, documentation__);
+}
+
+struct Service FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef ServiceBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_NAME = 4,
+ VT_CALLS = 6,
+ VT_ATTRIBUTES = 8,
+ VT_DOCUMENTATION = 10
+ };
+ const flatbuffers::String *name() const
+ {
+ return GetPointer<const flatbuffers::String *>(VT_NAME);
+ }
+ bool KeyCompareLessThan(const Service *o) const { return *name() < *o->name(); }
+ int KeyCompareWithValue(const char *val) const { return strcmp(name()->c_str(), val); }
+ const flatbuffers::Vector<flatbuffers::Offset<reflection::RPCCall>> *calls() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::RPCCall>> *>(
+ VT_CALLS);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(
+ VT_ATTRIBUTES);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(
+ VT_DOCUMENTATION);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffsetRequired(verifier, VT_NAME) &&
+ verifier.VerifyString(name()) && VerifyOffset(verifier, VT_CALLS) &&
+ verifier.VerifyVector(calls()) && verifier.VerifyVectorOfTables(calls()) &&
+ VerifyOffset(verifier, VT_ATTRIBUTES) && verifier.VerifyVector(attributes()) &&
+ verifier.VerifyVectorOfTables(attributes()) &&
+ VerifyOffset(verifier, VT_DOCUMENTATION) && verifier.VerifyVector(documentation()) &&
+ verifier.VerifyVectorOfStrings(documentation()) && verifier.EndTable();
+ }
+};
+
+struct ServiceBuilder
+{
+ typedef Service Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_name(flatbuffers::Offset<flatbuffers::String> name)
+ {
+ fbb_.AddOffset(Service::VT_NAME, name);
+ }
+ void add_calls(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::RPCCall>>> calls)
+ {
+ fbb_.AddOffset(Service::VT_CALLS, calls);
+ }
+ void add_attributes(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes)
+ {
+ fbb_.AddOffset(Service::VT_ATTRIBUTES, attributes);
+ }
+ void add_documentation(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>>
+ documentation)
+ {
+ fbb_.AddOffset(Service::VT_DOCUMENTATION, documentation);
+ }
+ explicit ServiceBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<Service> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Service>(end);
+ fbb_.Required(o, Service::VT_NAME);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Service> CreateService(
+ flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::Offset<flatbuffers::String> name = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::RPCCall>>> calls = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes =
+ 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation =
+ 0)
+{
+ ServiceBuilder builder_(_fbb);
+ builder_.add_documentation(documentation);
+ builder_.add_attributes(attributes);
+ builder_.add_calls(calls);
+ builder_.add_name(name);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<Service> CreateServiceDirect(
+ flatbuffers::FlatBufferBuilder &_fbb, const char *name = nullptr,
+ std::vector<flatbuffers::Offset<reflection::RPCCall>> *calls = nullptr,
+ std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
+ const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr)
+{
+ auto name__ = name ? _fbb.CreateString(name) : 0;
+ auto calls__ = calls ? _fbb.CreateVectorOfSortedTables<reflection::RPCCall>(calls) : 0;
+ auto attributes__ =
+ attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
+ auto documentation__ =
+ documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
+ return reflection::CreateService(_fbb, name__, calls__, attributes__, documentation__);
+}
+
+struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef SchemaBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_OBJECTS = 4,
+ VT_ENUMS = 6,
+ VT_FILE_IDENT = 8,
+ VT_FILE_EXT = 10,
+ VT_ROOT_TABLE = 12,
+ VT_SERVICES = 14,
+ VT_ADVANCED_FEATURES = 16
+ };
+ const flatbuffers::Vector<flatbuffers::Offset<reflection::Object>> *objects() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Object>> *>(
+ VT_OBJECTS);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>> *enums() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>> *>(VT_ENUMS);
+ }
+ const flatbuffers::String *file_ident() const
+ {
+ return GetPointer<const flatbuffers::String *>(VT_FILE_IDENT);
+ }
+ const flatbuffers::String *file_ext() const
+ {
+ return GetPointer<const flatbuffers::String *>(VT_FILE_EXT);
+ }
+ const reflection::Object *root_table() const
+ {
+ return GetPointer<const reflection::Object *>(VT_ROOT_TABLE);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<reflection::Service>> *services() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Service>> *>(
+ VT_SERVICES);
+ }
+ reflection::AdvancedFeatures advanced_features() const
+ {
+ return static_cast<reflection::AdvancedFeatures>(GetField<uint64_t>(VT_ADVANCED_FEATURES, 0));
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffsetRequired(verifier, VT_OBJECTS) &&
+ verifier.VerifyVector(objects()) && verifier.VerifyVectorOfTables(objects()) &&
+ VerifyOffsetRequired(verifier, VT_ENUMS) && verifier.VerifyVector(enums()) &&
+ verifier.VerifyVectorOfTables(enums()) && VerifyOffset(verifier, VT_FILE_IDENT) &&
+ verifier.VerifyString(file_ident()) && VerifyOffset(verifier, VT_FILE_EXT) &&
+ verifier.VerifyString(file_ext()) && VerifyOffset(verifier, VT_ROOT_TABLE) &&
+ verifier.VerifyTable(root_table()) && VerifyOffset(verifier, VT_SERVICES) &&
+ verifier.VerifyVector(services()) && verifier.VerifyVectorOfTables(services()) &&
+ VerifyField<uint64_t>(verifier, VT_ADVANCED_FEATURES) && verifier.EndTable();
+ }
+};
+
+struct SchemaBuilder
+{
+ typedef Schema Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_objects(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Object>>> objects)
+ {
+ fbb_.AddOffset(Schema::VT_OBJECTS, objects);
+ }
+ void
+ add_enums(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>>> enums)
+ {
+ fbb_.AddOffset(Schema::VT_ENUMS, enums);
+ }
+ void add_file_ident(flatbuffers::Offset<flatbuffers::String> file_ident)
+ {
+ fbb_.AddOffset(Schema::VT_FILE_IDENT, file_ident);
+ }
+ void add_file_ext(flatbuffers::Offset<flatbuffers::String> file_ext)
+ {
+ fbb_.AddOffset(Schema::VT_FILE_EXT, file_ext);
+ }
+ void add_root_table(flatbuffers::Offset<reflection::Object> root_table)
+ {
+ fbb_.AddOffset(Schema::VT_ROOT_TABLE, root_table);
+ }
+ void add_services(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Service>>> services)
+ {
+ fbb_.AddOffset(Schema::VT_SERVICES, services);
+ }
+ void add_advanced_features(reflection::AdvancedFeatures advanced_features)
+ {
+ fbb_.AddElement<uint64_t>(Schema::VT_ADVANCED_FEATURES,
+ static_cast<uint64_t>(advanced_features), 0);
+ }
+ explicit SchemaBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<Schema> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Schema>(end);
+ fbb_.Required(o, Schema::VT_OBJECTS);
+ fbb_.Required(o, Schema::VT_ENUMS);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Schema> CreateSchema(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Object>>> objects = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>>> enums = 0,
+ flatbuffers::Offset<flatbuffers::String> file_ident = 0,
+ flatbuffers::Offset<flatbuffers::String> file_ext = 0,
+ flatbuffers::Offset<reflection::Object> root_table = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Service>>> services = 0,
+ reflection::AdvancedFeatures advanced_features = static_cast<reflection::AdvancedFeatures>(0))
+{
+ SchemaBuilder builder_(_fbb);
+ builder_.add_advanced_features(advanced_features);
+ builder_.add_services(services);
+ builder_.add_root_table(root_table);
+ builder_.add_file_ext(file_ext);
+ builder_.add_file_ident(file_ident);
+ builder_.add_enums(enums);
+ builder_.add_objects(objects);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<Schema> CreateSchemaDirect(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ std::vector<flatbuffers::Offset<reflection::Object>> *objects = nullptr,
+ std::vector<flatbuffers::Offset<reflection::Enum>> *enums = nullptr,
+ const char *file_ident = nullptr, const char *file_ext = nullptr,
+ flatbuffers::Offset<reflection::Object> root_table = 0,
+ std::vector<flatbuffers::Offset<reflection::Service>> *services = nullptr,
+ reflection::AdvancedFeatures advanced_features = static_cast<reflection::AdvancedFeatures>(0))
+{
+ auto objects__ = objects ? _fbb.CreateVectorOfSortedTables<reflection::Object>(objects) : 0;
+ auto enums__ = enums ? _fbb.CreateVectorOfSortedTables<reflection::Enum>(enums) : 0;
+ auto file_ident__ = file_ident ? _fbb.CreateString(file_ident) : 0;
+ auto file_ext__ = file_ext ? _fbb.CreateString(file_ext) : 0;
+ auto services__ = services ? _fbb.CreateVectorOfSortedTables<reflection::Service>(services) : 0;
+ return reflection::CreateSchema(_fbb, objects__, enums__, file_ident__, file_ext__, root_table,
+ services__, advanced_features);
+}
+
+inline const reflection::Schema *GetSchema(const void *buf)
+{
+ return flatbuffers::GetRoot<reflection::Schema>(buf);
+}
+
+inline const reflection::Schema *GetSizePrefixedSchema(const void *buf)
+{
+ return flatbuffers::GetSizePrefixedRoot<reflection::Schema>(buf);
+}
+
+inline const char *SchemaIdentifier() { return "BFBS"; }
+
+inline bool SchemaBufferHasIdentifier(const void *buf)
+{
+ return flatbuffers::BufferHasIdentifier(buf, SchemaIdentifier());
+}
+
+inline bool VerifySchemaBuffer(flatbuffers::Verifier &verifier)
+{
+ return verifier.VerifyBuffer<reflection::Schema>(SchemaIdentifier());
+}
+
+inline bool VerifySizePrefixedSchemaBuffer(flatbuffers::Verifier &verifier)
+{
+ return verifier.VerifySizePrefixedBuffer<reflection::Schema>(SchemaIdentifier());
+}
+
+inline const char *SchemaExtension() { return "bfbs"; }
+
+inline void FinishSchemaBuffer(flatbuffers::FlatBufferBuilder &fbb,
+ flatbuffers::Offset<reflection::Schema> root)
+{
+ fbb.Finish(root, SchemaIdentifier());
+}
+
+inline void FinishSizePrefixedSchemaBuffer(flatbuffers::FlatBufferBuilder &fbb,
+ flatbuffers::Offset<reflection::Schema> root)
+{
+ fbb.FinishSizePrefixed(root, SchemaIdentifier());
+}
+
+} // namespace reflection
+
+#endif // FLATBUFFERS_GENERATED_REFLECTION_REFLECTION_H_
diff --git a/onert-micro/externals/flatbuffers/registry.h b/onert-micro/externals/flatbuffers/registry.h
new file mode 100644
index 000000000..c06bd5687
--- /dev/null
+++ b/onert-micro/externals/flatbuffers/registry.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2017 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLATBUFFERS_REGISTRY_H_
+#define FLATBUFFERS_REGISTRY_H_
+
+#include "flatbuffers/idl.h"
+
+namespace flatbuffers
+{
+
+// Convenience class to easily parse or generate text for arbitrary FlatBuffers.
+// Simply pre-populate it with all schema filenames that may be in use, and
+// This class will look them up using the file_identifier declared in the
+// schema.
+class Registry
+{
+public:
+ // Call this for all schemas that may be in use. The identifier has
+ // a function in the generated code, e.g. MonsterIdentifier().
+ void Register(const char *file_identifier, const char *schema_path)
+ {
+ Schema schema;
+ schema.path_ = schema_path;
+ schemas_[file_identifier] = schema;
+ }
+
+ // Generate text from an arbitrary FlatBuffer by looking up its
+ // file_identifier in the registry.
+ bool FlatBufferToText(const uint8_t *flatbuf, size_t len, std::string *dest)
+ {
+ // Get the identifier out of the buffer.
+ // If the buffer is truncated, exit.
+ if (len < sizeof(uoffset_t) + FlatBufferBuilder::kFileIdentifierLength)
+ {
+ lasterror_ = "buffer truncated";
+ return false;
+ }
+ std::string ident(reinterpret_cast<const char *>(flatbuf) + sizeof(uoffset_t),
+ FlatBufferBuilder::kFileIdentifierLength);
+ // Load and parse the schema.
+ Parser parser;
+ if (!LoadSchema(ident, &parser))
+ return false;
+ // Now we're ready to generate text.
+ if (!GenerateText(parser, flatbuf, dest))
+ {
+ lasterror_ = "unable to generate text for FlatBuffer binary";
+ return false;
+ }
+ return true;
+ }
+
+ // Converts a binary buffer to text using one of the schemas in the registry,
+ // use the file_identifier to indicate which.
+ // If DetachedBuffer::data() is null then parsing failed.
+ DetachedBuffer TextToFlatBuffer(const char *text, const char *file_identifier)
+ {
+ // Load and parse the schema.
+ Parser parser;
+ if (!LoadSchema(file_identifier, &parser))
+ return DetachedBuffer();
+ // Parse the text.
+ if (!parser.Parse(text))
+ {
+ lasterror_ = parser.error_;
+ return DetachedBuffer();
+ }
+ // We have a valid FlatBuffer. Detach it from the builder and return.
+ return parser.builder_.Release();
+ }
+
+ // Modify any parsing / output options used by the other functions.
+ void SetOptions(const IDLOptions &opts) { opts_ = opts; }
+
+ // If schemas used contain include statements, call this function for every
+ // directory the parser should search them for.
+ void AddIncludeDirectory(const char *path) { include_paths_.push_back(path); }
+
+ // Returns a human readable error if any of the above functions fail.
+ const std::string &GetLastError() { return lasterror_; }
+
+private:
+ bool LoadSchema(const std::string &ident, Parser *parser)
+ {
+ // Find the schema, if not, exit.
+ auto it = schemas_.find(ident);
+ if (it == schemas_.end())
+ {
+ // Don't attach the identifier, since it may not be human readable.
+ lasterror_ = "identifier for this buffer not in the registry";
+ return false;
+ }
+ auto &schema = it->second;
+ // Load the schema from disk. If not, exit.
+ std::string schematext;
+ if (!LoadFile(schema.path_.c_str(), false, &schematext))
+ {
+ lasterror_ = "could not load schema: " + schema.path_;
+ return false;
+ }
+ // Parse schema.
+ parser->opts = opts_;
+ if (!parser->Parse(schematext.c_str(), vector_data(include_paths_), schema.path_.c_str()))
+ {
+ lasterror_ = parser->error_;
+ return false;
+ }
+ return true;
+ }
+
+ struct Schema
+ {
+ std::string path_;
+ // TODO(wvo) optionally cache schema file or parsed schema here.
+ };
+
+ std::string lasterror_;
+ IDLOptions opts_;
+ std::vector<const char *> include_paths_;
+ std::map<std::string, Schema> schemas_;
+};
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_REGISTRY_H_
diff --git a/onert-micro/externals/flatbuffers/stl_emulation.h b/onert-micro/externals/flatbuffers/stl_emulation.h
new file mode 100644
index 000000000..3f11fb9cb
--- /dev/null
+++ b/onert-micro/externals/flatbuffers/stl_emulation.h
@@ -0,0 +1,674 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2017 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLATBUFFERS_STL_EMULATION_H_
+#define FLATBUFFERS_STL_EMULATION_H_
+
+// clang-format off
+#include "flatbuffers/base.h"
+
+#include <string>
+#include <type_traits>
+#include <vector>
+#include <memory>
+#include <limits>
+
+#if defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL)
+ #define FLATBUFFERS_CPP98_STL
+#endif // defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL)
+
+#if defined(FLATBUFFERS_CPP98_STL)
+ #include <cctype>
+#endif // defined(FLATBUFFERS_CPP98_STL)
+
+// Detect C++17 compatible compiler.
+// __cplusplus >= 201703L - a compiler has support of 'static inline' variables.
+#if defined(FLATBUFFERS_USE_STD_OPTIONAL) \
+ || (defined(__cplusplus) && __cplusplus >= 201703L) \
+ || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L))
+ #include <optional>
+ #ifndef FLATBUFFERS_USE_STD_OPTIONAL
+ #define FLATBUFFERS_USE_STD_OPTIONAL
+ #endif
+#endif // defined(FLATBUFFERS_USE_STD_OPTIONAL) ...
+
+// The __cpp_lib_span is the predefined feature macro.
+#if defined(FLATBUFFERS_USE_STD_SPAN)
+ #include <span>
+#elif defined(__cpp_lib_span) && defined(__has_include)
+ #if __has_include(<span>)
+ #include <span>
+ #define FLATBUFFERS_USE_STD_SPAN
+ #endif
+#else
+ // Disable non-trivial ctors if FLATBUFFERS_SPAN_MINIMAL defined.
+ #if !defined(FLATBUFFERS_TEMPLATES_ALIASES) || defined(FLATBUFFERS_CPP98_STL)
+ #define FLATBUFFERS_SPAN_MINIMAL
+ #else
+ // Enable implicit construction of a span<T,N> from a std::array<T,N>.
+ #include <array>
+ #endif
+#endif // defined(FLATBUFFERS_USE_STD_SPAN)
+
+// This header provides backwards compatibility for C++98 STLs like stlport.
+namespace flatbuffers {
+
+// Retrieve ::back() from a string in a way that is compatible with pre C++11
+// STLs (e.g stlport).
+inline char& string_back(std::string &value) {
+ return value[value.length() - 1];
+}
+
+inline char string_back(const std::string &value) {
+ return value[value.length() - 1];
+}
+
+// Helper method that retrieves ::data() from a vector in a way that is
+// compatible with pre C++11 STLs (e.g stlport).
+template <typename T> inline T *vector_data(std::vector<T> &vector) {
+ // In some debug environments, operator[] does bounds checking, so &vector[0]
+ // can't be used.
+ return vector.empty() ? nullptr : &vector[0];
+}
+
+template <typename T> inline const T *vector_data(
+ const std::vector<T> &vector) {
+ return vector.empty() ? nullptr : &vector[0];
+}
+
+template <typename T, typename V>
+inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
+ #if defined(FLATBUFFERS_CPP98_STL)
+ vector->push_back(data);
+ #else
+ vector->emplace_back(std::forward<V>(data));
+ #endif // defined(FLATBUFFERS_CPP98_STL)
+}
+
+#ifndef FLATBUFFERS_CPP98_STL
+ #if defined(FLATBUFFERS_TEMPLATES_ALIASES)
+ template <typename T>
+ using numeric_limits = std::numeric_limits<T>;
+ #else
+ template <typename T> class numeric_limits :
+ public std::numeric_limits<T> {};
+ #endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
+#else
+ template <typename T> class numeric_limits :
+ public std::numeric_limits<T> {
+ public:
+ // Android NDK fix.
+ static T lowest() {
+ return std::numeric_limits<T>::min();
+ }
+ };
+
+ template <> class numeric_limits<float> :
+ public std::numeric_limits<float> {
+ public:
+ static float lowest() { return -FLT_MAX; }
+ };
+
+ template <> class numeric_limits<double> :
+ public std::numeric_limits<double> {
+ public:
+ static double lowest() { return -DBL_MAX; }
+ };
+
+ template <> class numeric_limits<unsigned long long> {
+ public:
+ static unsigned long long min() { return 0ULL; }
+ static unsigned long long max() { return ~0ULL; }
+ static unsigned long long lowest() {
+ return numeric_limits<unsigned long long>::min();
+ }
+ };
+
+ template <> class numeric_limits<long long> {
+ public:
+ static long long min() {
+ return static_cast<long long>(1ULL << ((sizeof(long long) << 3) - 1));
+ }
+ static long long max() {
+ return static_cast<long long>(
+ (1ULL << ((sizeof(long long) << 3) - 1)) - 1);
+ }
+ static long long lowest() {
+ return numeric_limits<long long>::min();
+ }
+ };
+#endif // FLATBUFFERS_CPP98_STL
+
+#if defined(FLATBUFFERS_TEMPLATES_ALIASES)
+ #ifndef FLATBUFFERS_CPP98_STL
+ template <typename T> using is_scalar = std::is_scalar<T>;
+ template <typename T, typename U> using is_same = std::is_same<T,U>;
+ template <typename T> using is_floating_point = std::is_floating_point<T>;
+ template <typename T> using is_unsigned = std::is_unsigned<T>;
+ template <typename T> using is_enum = std::is_enum<T>;
+ template <typename T> using make_unsigned = std::make_unsigned<T>;
+ template<bool B, class T, class F>
+ using conditional = std::conditional<B, T, F>;
+ template<class T, T v>
+ using integral_constant = std::integral_constant<T, v>;
+ template <bool B>
+ using bool_constant = integral_constant<bool, B>;
+ #else
+ // Map C++ TR1 templates defined by stlport.
+ template <typename T> using is_scalar = std::tr1::is_scalar<T>;
+ template <typename T, typename U> using is_same = std::tr1::is_same<T,U>;
+ template <typename T> using is_floating_point =
+ std::tr1::is_floating_point<T>;
+ template <typename T> using is_unsigned = std::tr1::is_unsigned<T>;
+ template <typename T> using is_enum = std::tr1::is_enum<T>;
+ // Android NDK doesn't have std::make_unsigned or std::tr1::make_unsigned.
+ template<typename T> struct make_unsigned {
+ static_assert(is_unsigned<T>::value, "Specialization not implemented!");
+ using type = T;
+ };
+ template<> struct make_unsigned<char> { using type = unsigned char; };
+ template<> struct make_unsigned<short> { using type = unsigned short; };
+ template<> struct make_unsigned<int> { using type = unsigned int; };
+ template<> struct make_unsigned<long> { using type = unsigned long; };
+ template<>
+ struct make_unsigned<long long> { using type = unsigned long long; };
+ template<bool B, class T, class F>
+ using conditional = std::tr1::conditional<B, T, F>;
+ template<class T, T v>
+ using integral_constant = std::tr1::integral_constant<T, v>;
+ template <bool B>
+ using bool_constant = integral_constant<bool, B>;
+ #endif // !FLATBUFFERS_CPP98_STL
+#else
+ // MSVC 2010 doesn't support C++11 aliases.
+ template <typename T> struct is_scalar : public std::is_scalar<T> {};
+ template <typename T, typename U> struct is_same : public std::is_same<T,U> {};
+ template <typename T> struct is_floating_point :
+ public std::is_floating_point<T> {};
+ template <typename T> struct is_unsigned : public std::is_unsigned<T> {};
+ template <typename T> struct is_enum : public std::is_enum<T> {};
+ template <typename T> struct make_unsigned : public std::make_unsigned<T> {};
+ template<bool B, class T, class F>
+ struct conditional : public std::conditional<B, T, F> {};
+ template<class T, T v>
+ struct integral_constant : public std::integral_constant<T, v> {};
+ template <bool B>
+ struct bool_constant : public integral_constant<bool, B> {};
+#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
+
+#ifndef FLATBUFFERS_CPP98_STL
+ #if defined(FLATBUFFERS_TEMPLATES_ALIASES)
+ template <class T> using unique_ptr = std::unique_ptr<T>;
+ #else
+ // MSVC 2010 doesn't support C++11 aliases.
+ // We're manually "aliasing" the class here as we want to bring unique_ptr
+ // into the flatbuffers namespace. We have unique_ptr in the flatbuffers
+ // namespace we have a completely independent implementation (see below)
+ // for C++98 STL implementations.
+ template <class T> class unique_ptr : public std::unique_ptr<T> {
+ public:
+ unique_ptr() {}
+ explicit unique_ptr(T* p) : std::unique_ptr<T>(p) {}
+ unique_ptr(std::unique_ptr<T>&& u) { *this = std::move(u); }
+ unique_ptr(unique_ptr&& u) { *this = std::move(u); }
+ unique_ptr& operator=(std::unique_ptr<T>&& u) {
+ std::unique_ptr<T>::reset(u.release());
+ return *this;
+ }
+ unique_ptr& operator=(unique_ptr&& u) {
+ std::unique_ptr<T>::reset(u.release());
+ return *this;
+ }
+ unique_ptr& operator=(T* p) {
+ return std::unique_ptr<T>::operator=(p);
+ }
+ };
+ #endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
+#else
+ // Very limited implementation of unique_ptr.
+ // This is provided simply to allow the C++ code generated from the default
+ // settings to function in C++98 environments with no modifications.
+ template <class T> class unique_ptr {
+ public:
+ typedef T element_type;
+
+ unique_ptr() : ptr_(nullptr) {}
+ explicit unique_ptr(T* p) : ptr_(p) {}
+ unique_ptr(unique_ptr&& u) : ptr_(nullptr) { reset(u.release()); }
+ unique_ptr(const unique_ptr& u) : ptr_(nullptr) {
+ reset(const_cast<unique_ptr*>(&u)->release());
+ }
+ ~unique_ptr() { reset(); }
+
+ unique_ptr& operator=(const unique_ptr& u) {
+ reset(const_cast<unique_ptr*>(&u)->release());
+ return *this;
+ }
+
+ unique_ptr& operator=(unique_ptr&& u) {
+ reset(u.release());
+ return *this;
+ }
+
+ unique_ptr& operator=(T* p) {
+ reset(p);
+ return *this;
+ }
+
+ const T& operator*() const { return *ptr_; }
+ T* operator->() const { return ptr_; }
+ T* get() const noexcept { return ptr_; }
+ explicit operator bool() const { return ptr_ != nullptr; }
+
+ // modifiers
+ T* release() {
+ T* value = ptr_;
+ ptr_ = nullptr;
+ return value;
+ }
+
+ void reset(T* p = nullptr) {
+ T* value = ptr_;
+ ptr_ = p;
+ if (value) delete value;
+ }
+
+ void swap(unique_ptr& u) {
+ T* temp_ptr = ptr_;
+ ptr_ = u.ptr_;
+ u.ptr_ = temp_ptr;
+ }
+
+ private:
+ T* ptr_;
+ };
+
+ template <class T> bool operator==(const unique_ptr<T>& x,
+ const unique_ptr<T>& y) {
+ return x.get() == y.get();
+ }
+
+ template <class T, class D> bool operator==(const unique_ptr<T>& x,
+ const D* y) {
+ return static_cast<D*>(x.get()) == y;
+ }
+
+ template <class T> bool operator==(const unique_ptr<T>& x, intptr_t y) {
+ return reinterpret_cast<intptr_t>(x.get()) == y;
+ }
+
+ template <class T> bool operator!=(const unique_ptr<T>& x, decltype(nullptr)) {
+ return !!x;
+ }
+
+ template <class T> bool operator!=(decltype(nullptr), const unique_ptr<T>& x) {
+ return !!x;
+ }
+
+ template <class T> bool operator==(const unique_ptr<T>& x, decltype(nullptr)) {
+ return !x;
+ }
+
+ template <class T> bool operator==(decltype(nullptr), const unique_ptr<T>& x) {
+ return !x;
+ }
+
+#endif // !FLATBUFFERS_CPP98_STL
+
+#ifdef FLATBUFFERS_USE_STD_OPTIONAL
+template<class T>
+using Optional = std::optional<T>;
+using nullopt_t = std::nullopt_t;
+inline constexpr nullopt_t nullopt = std::nullopt;
+
+#else
+// Limited implementation of Optional<T> type for a scalar T.
+// This implementation limited by trivial types compatible with
+// std::is_arithmetic<T> or std::is_enum<T> type traits.
+
+// A tag to indicate an empty flatbuffers::optional<T>.
+struct nullopt_t {
+ explicit FLATBUFFERS_CONSTEXPR_CPP11 nullopt_t(int) {}
+};
+
+#if defined(FLATBUFFERS_CONSTEXPR_DEFINED)
+ namespace internal {
+ template <class> struct nullopt_holder {
+ static constexpr nullopt_t instance_ = nullopt_t(0);
+ };
+ template<class Dummy>
+ constexpr nullopt_t nullopt_holder<Dummy>::instance_;
+ }
+ static constexpr const nullopt_t &nullopt = internal::nullopt_holder<void>::instance_;
+
+#else
+ namespace internal {
+ template <class> struct nullopt_holder {
+ static const nullopt_t instance_;
+ };
+ template<class Dummy>
+ const nullopt_t nullopt_holder<Dummy>::instance_ = nullopt_t(0);
+ }
+ static const nullopt_t &nullopt = internal::nullopt_holder<void>::instance_;
+
+#endif
+
+template<class T>
+class Optional FLATBUFFERS_FINAL_CLASS {
+ // Non-scalar 'T' would extremely complicated Optional<T>.
+ // Use is_scalar<T> checking because flatbuffers flatbuffers::is_arithmetic<T>
+ // isn't implemented.
+ static_assert(flatbuffers::is_scalar<T>::value, "unexpected type T");
+
+ public:
+ ~Optional() {}
+
+ FLATBUFFERS_CONSTEXPR_CPP11 Optional() FLATBUFFERS_NOEXCEPT
+ : value_(), has_value_(false) {}
+
+ FLATBUFFERS_CONSTEXPR_CPP11 Optional(nullopt_t) FLATBUFFERS_NOEXCEPT
+ : value_(), has_value_(false) {}
+
+ FLATBUFFERS_CONSTEXPR_CPP11 Optional(T val) FLATBUFFERS_NOEXCEPT
+ : value_(val), has_value_(true) {}
+
+ FLATBUFFERS_CONSTEXPR_CPP11 Optional(const Optional &other) FLATBUFFERS_NOEXCEPT
+ : value_(other.value_), has_value_(other.has_value_) {}
+
+ FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(const Optional &other) FLATBUFFERS_NOEXCEPT {
+ value_ = other.value_;
+ has_value_ = other.has_value_;
+ return *this;
+ }
+
+ FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(nullopt_t) FLATBUFFERS_NOEXCEPT {
+ value_ = T();
+ has_value_ = false;
+ return *this;
+ }
+
+ FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(T val) FLATBUFFERS_NOEXCEPT {
+ value_ = val;
+ has_value_ = true;
+ return *this;
+ }
+
+ void reset() FLATBUFFERS_NOEXCEPT {
+ *this = nullopt;
+ }
+
+ void swap(Optional &other) FLATBUFFERS_NOEXCEPT {
+ std::swap(value_, other.value_);
+ std::swap(has_value_, other.has_value_);
+ }
+
+ FLATBUFFERS_CONSTEXPR_CPP11 FLATBUFFERS_EXPLICIT_CPP11 operator bool() const FLATBUFFERS_NOEXCEPT {
+ return has_value_;
+ }
+
+ FLATBUFFERS_CONSTEXPR_CPP11 bool has_value() const FLATBUFFERS_NOEXCEPT {
+ return has_value_;
+ }
+
+ FLATBUFFERS_CONSTEXPR_CPP11 const T& operator*() const FLATBUFFERS_NOEXCEPT {
+ return value_;
+ }
+
+ const T& value() const {
+ FLATBUFFERS_ASSERT(has_value());
+ return value_;
+ }
+
+ T value_or(T default_value) const FLATBUFFERS_NOEXCEPT {
+ return has_value() ? value_ : default_value;
+ }
+
+ private:
+ T value_;
+ bool has_value_;
+};
+
+template<class T>
+FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& opt, nullopt_t) FLATBUFFERS_NOEXCEPT {
+ return !opt;
+}
+template<class T>
+FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(nullopt_t, const Optional<T>& opt) FLATBUFFERS_NOEXCEPT {
+ return !opt;
+}
+
+template<class T, class U>
+FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& lhs, const U& rhs) FLATBUFFERS_NOEXCEPT {
+ return static_cast<bool>(lhs) && (*lhs == rhs);
+}
+
+template<class T, class U>
+FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const T& lhs, const Optional<U>& rhs) FLATBUFFERS_NOEXCEPT {
+ return static_cast<bool>(rhs) && (lhs == *rhs);
+}
+
+template<class T, class U>
+FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& lhs, const Optional<U>& rhs) FLATBUFFERS_NOEXCEPT {
+ return static_cast<bool>(lhs) != static_cast<bool>(rhs)
+ ? false
+ : !static_cast<bool>(lhs) ? false : (*lhs == *rhs);
+}
+#endif // FLATBUFFERS_USE_STD_OPTIONAL
+
+
+// Very limited and naive partial implementation of C++20 std::span<T,Extent>.
+#if defined(FLATBUFFERS_USE_STD_SPAN)
+ inline constexpr std::size_t dynamic_extent = std::dynamic_extent;
+ template<class T, std::size_t Extent = std::dynamic_extent>
+ using span = std::span<T, Extent>;
+
+#else // !defined(FLATBUFFERS_USE_STD_SPAN)
+FLATBUFFERS_CONSTEXPR std::size_t dynamic_extent = static_cast<std::size_t>(-1);
+
+// Exclude this code if MSVC2010 or non-STL Android is active.
+// The non-STL Android doesn't have `std::is_convertible` required for SFINAE.
+#if !defined(FLATBUFFERS_SPAN_MINIMAL)
+namespace internal {
+ // This is SFINAE helper class for checking of a common condition:
+ // > This overload only participates in overload resolution
+ // > Check whether a pointer to an array of U can be converted
+ // > to a pointer to an array of E.
+ // This helper is used for checking of 'U -> const U'.
+ template<class E, std::size_t Extent, class U, std::size_t N>
+ struct is_span_convertable {
+ using type =
+ typename std::conditional<std::is_convertible<U (*)[], E (*)[]>::value
+ && (Extent == dynamic_extent || N == Extent),
+ int, void>::type;
+ };
+
+} // namespace internal
+#endif // !defined(FLATBUFFERS_SPAN_MINIMAL)
+
+// T - element type; must be a complete type that is not an abstract
+// class type.
+// Extent - the number of elements in the sequence, or dynamic.
+template<class T, std::size_t Extent = dynamic_extent>
+class span FLATBUFFERS_FINAL_CLASS {
+ public:
+ typedef T element_type;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef std::size_t size_type;
+
+ static FLATBUFFERS_CONSTEXPR size_type extent = Extent;
+
+ // Returns the number of elements in the span.
+ FLATBUFFERS_CONSTEXPR_CPP11 size_type size() const FLATBUFFERS_NOEXCEPT {
+ return count_;
+ }
+
+ // Returns the size of the sequence in bytes.
+ FLATBUFFERS_CONSTEXPR_CPP11
+ size_type size_bytes() const FLATBUFFERS_NOEXCEPT {
+ return size() * sizeof(element_type);
+ }
+
+ // Checks if the span is empty.
+ FLATBUFFERS_CONSTEXPR_CPP11 bool empty() const FLATBUFFERS_NOEXCEPT {
+ return size() == 0;
+ }
+
+ // Returns a pointer to the beginning of the sequence.
+ FLATBUFFERS_CONSTEXPR_CPP11 pointer data() const FLATBUFFERS_NOEXCEPT {
+ return data_;
+ }
+
+ // Returns a reference to the idx-th element of the sequence.
+ // The behavior is undefined if the idx is greater than or equal to size().
+ FLATBUFFERS_CONSTEXPR_CPP11 reference operator[](size_type idx) const {
+ return data()[idx];
+ }
+
+ FLATBUFFERS_CONSTEXPR_CPP11 span(const span &other) FLATBUFFERS_NOEXCEPT
+ : data_(other.data_), count_(other.count_) {}
+
+ FLATBUFFERS_CONSTEXPR_CPP14 span &operator=(const span &other)
+ FLATBUFFERS_NOEXCEPT {
+ data_ = other.data_;
+ count_ = other.count_;
+ }
+
+ // Limited implementation of
+ // `template <class It> constexpr std::span(It first, size_type count);`.
+ //
+ // Constructs a span that is a view over the range [first, first + count);
+ // the resulting span has: data() == first and size() == count.
+ // The behavior is undefined if [first, first + count) is not a valid range,
+ // or if (extent != flatbuffers::dynamic_extent && count != extent).
+ FLATBUFFERS_CONSTEXPR_CPP11
+ explicit span(pointer first, size_type count) FLATBUFFERS_NOEXCEPT
+ : data_ (Extent == dynamic_extent ? first : (Extent == count ? first : nullptr)),
+ count_(Extent == dynamic_extent ? count : (Extent == count ? Extent : 0)) {
+ // Make span empty if the count argument is incompatible with span<T,N>.
+ }
+
+ // Exclude this code if MSVC2010 is active. The MSVC2010 isn't C++11
+ // compliant, it doesn't support default template arguments for functions.
+ #if defined(FLATBUFFERS_SPAN_MINIMAL)
+ FLATBUFFERS_CONSTEXPR_CPP11 span() FLATBUFFERS_NOEXCEPT : data_(nullptr),
+ count_(0) {
+ static_assert(extent == 0 || extent == dynamic_extent, "invalid span");
+ }
+
+ #else
+ // Constructs an empty span whose data() == nullptr and size() == 0.
+ // This overload only participates in overload resolution if
+ // extent == 0 || extent == flatbuffers::dynamic_extent.
+ // A dummy template argument N is need dependency for SFINAE.
+ template<std::size_t N = 0,
+ typename internal::is_span_convertable<element_type, Extent, element_type, (N - N)>::type = 0>
+ FLATBUFFERS_CONSTEXPR_CPP11 span() FLATBUFFERS_NOEXCEPT : data_(nullptr),
+ count_(0) {
+ static_assert(extent == 0 || extent == dynamic_extent, "invalid span");
+ }
+
+ // Constructs a span that is a view over the array arr; the resulting span
+ // has size() == N and data() == std::data(arr). These overloads only
+ // participate in overload resolution if
+ // extent == std::dynamic_extent || N == extent is true and
+ // std::remove_pointer_t<decltype(std::data(arr))>(*)[]
+ // is convertible to element_type (*)[].
+ template<std::size_t N,
+ typename internal::is_span_convertable<element_type, Extent, element_type, N>::type = 0>
+ FLATBUFFERS_CONSTEXPR_CPP11 span(element_type (&arr)[N]) FLATBUFFERS_NOEXCEPT
+ : data_(arr), count_(N) {}
+
+ template<class U, std::size_t N,
+ typename internal::is_span_convertable<element_type, Extent, U, N>::type = 0>
+ FLATBUFFERS_CONSTEXPR_CPP11 span(std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT
+ : data_(arr.data()), count_(N) {}
+
+ //template<class U, std::size_t N,
+ // int = 0>
+ //FLATBUFFERS_CONSTEXPR_CPP11 span(std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT
+ // : data_(arr.data()), count_(N) {}
+
+ template<class U, std::size_t N,
+ typename internal::is_span_convertable<element_type, Extent, U, N>::type = 0>
+ FLATBUFFERS_CONSTEXPR_CPP11 span(const std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT
+ : data_(arr.data()), count_(N) {}
+
+ // Converting constructor from another span s;
+ // the resulting span has size() == s.size() and data() == s.data().
+ // This overload only participates in overload resolution
+ // if extent == std::dynamic_extent || N == extent is true and U (*)[]
+ // is convertible to element_type (*)[].
+ template<class U, std::size_t N,
+ typename internal::is_span_convertable<element_type, Extent, U, N>::type = 0>
+ FLATBUFFERS_CONSTEXPR_CPP11 span(const flatbuffers::span<U, N> &s) FLATBUFFERS_NOEXCEPT
+ : span(s.data(), s.size()) {
+ }
+
+ #endif // !defined(FLATBUFFERS_SPAN_MINIMAL)
+
+ private:
+ // This is a naive implementation with 'count_' member even if (Extent != dynamic_extent).
+ pointer const data_;
+ const size_type count_;
+};
+
+ #if !defined(FLATBUFFERS_SPAN_MINIMAL)
+ template<class U, std::size_t N>
+ FLATBUFFERS_CONSTEXPR_CPP11
+ flatbuffers::span<U, N> make_span(U(&arr)[N]) FLATBUFFERS_NOEXCEPT {
+ return span<U, N>(arr);
+ }
+
+ template<class U, std::size_t N>
+ FLATBUFFERS_CONSTEXPR_CPP11
+ flatbuffers::span<const U, N> make_span(const U(&arr)[N]) FLATBUFFERS_NOEXCEPT {
+ return span<const U, N>(arr);
+ }
+
+ template<class U, std::size_t N>
+ FLATBUFFERS_CONSTEXPR_CPP11
+ flatbuffers::span<U, N> make_span(std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
+ return span<U, N>(arr);
+ }
+
+ template<class U, std::size_t N>
+ FLATBUFFERS_CONSTEXPR_CPP11
+ flatbuffers::span<const U, N> make_span(const std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
+ return span<const U, N>(arr);
+ }
+
+ template<class U, std::size_t N>
+ FLATBUFFERS_CONSTEXPR_CPP11
+ flatbuffers::span<U, dynamic_extent> make_span(U *first, std::size_t count) FLATBUFFERS_NOEXCEPT {
+ return span<U, dynamic_extent>(first, count);
+ }
+
+ template<class U, std::size_t N>
+ FLATBUFFERS_CONSTEXPR_CPP11
+ flatbuffers::span<const U, dynamic_extent> make_span(const U *first, std::size_t count) FLATBUFFERS_NOEXCEPT {
+ return span<const U, dynamic_extent>(first, count);
+ }
+#endif
+
+#endif // defined(FLATBUFFERS_USE_STD_SPAN)
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_STL_EMULATION_H_
diff --git a/onert-micro/externals/flatbuffers/util.h b/onert-micro/externals/flatbuffers/util.h
new file mode 100644
index 000000000..e255801af
--- /dev/null
+++ b/onert-micro/externals/flatbuffers/util.h
@@ -0,0 +1,799 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2014 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLATBUFFERS_UTIL_H_
+#define FLATBUFFERS_UTIL_H_
+
+#include <errno.h>
+
+#include "flatbuffers/base.h"
+#include "flatbuffers/stl_emulation.h"
+
+#ifndef FLATBUFFERS_PREFER_PRINTF
+#include <sstream>
+#else // FLATBUFFERS_PREFER_PRINTF
+#include <float.h>
+#include <stdio.h>
+#endif // FLATBUFFERS_PREFER_PRINTF
+
+#include <iomanip>
+#include <string>
+
+namespace flatbuffers
+{
+
+// @locale-independent functions for ASCII characters set.
+
+// Fast checking that character lies in closed range: [a <= x <= b]
+// using one compare (conditional branch) operator.
+inline bool check_ascii_range(char x, char a, char b)
+{
+ FLATBUFFERS_ASSERT(a <= b);
+ // (Hacker's Delight): `a <= x <= b` <=> `(x-a) <={u} (b-a)`.
+ // The x, a, b will be promoted to int and subtracted without overflow.
+ return static_cast<unsigned int>(x - a) <= static_cast<unsigned int>(b - a);
+}
+
+// Case-insensitive isalpha
+inline bool is_alpha(char c)
+{
+ // ASCII only: alpha to upper case => reset bit 0x20 (~0x20 = 0xDF).
+ return check_ascii_range(c & 0xDF, 'a' & 0xDF, 'z' & 0xDF);
+}
+
+// Check for uppercase alpha
+inline bool is_alpha_upper(char c) { return check_ascii_range(c, 'A', 'Z'); }
+
+// Check (case-insensitive) that `c` is equal to alpha.
+inline bool is_alpha_char(char c, char alpha)
+{
+ FLATBUFFERS_ASSERT(is_alpha(alpha));
+ // ASCII only: alpha to upper case => reset bit 0x20 (~0x20 = 0xDF).
+ return ((c & 0xDF) == (alpha & 0xDF));
+}
+
+// https://en.cppreference.com/w/cpp/string/byte/isxdigit
+// isdigit and isxdigit are the only standard narrow character classification
+// functions that are not affected by the currently installed C locale. although
+// some implementations (e.g. Microsoft in 1252 codepage) may classify
+// additional single-byte characters as digits.
+inline bool is_digit(char c) { return check_ascii_range(c, '0', '9'); }
+
+inline bool is_xdigit(char c)
+{
+ // Replace by look-up table.
+ return is_digit(c) || check_ascii_range(c & 0xDF, 'a' & 0xDF, 'f' & 0xDF);
+}
+
+// Case-insensitive isalnum
+inline bool is_alnum(char c) { return is_alpha(c) || is_digit(c); }
+
+inline char CharToUpper(char c)
+{
+ return static_cast<char>(::toupper(static_cast<unsigned char>(c)));
+}
+
+inline char CharToLower(char c)
+{
+ return static_cast<char>(::tolower(static_cast<unsigned char>(c)));
+}
+
+// @end-locale-independent functions for ASCII character set
+
+#ifdef FLATBUFFERS_PREFER_PRINTF
+template <typename T> size_t IntToDigitCount(T t)
+{
+ size_t digit_count = 0;
+ // Count the sign for negative numbers
+ if (t < 0)
+ digit_count++;
+ // Count a single 0 left of the dot for fractional numbers
+ if (-1 < t && t < 1)
+ digit_count++;
+ // Count digits until fractional part
+ T eps = std::numeric_limits<float>::epsilon();
+ while (t <= (-1 + eps) || (1 - eps) <= t)
+ {
+ t /= 10;
+ digit_count++;
+ }
+ return digit_count;
+}
+
+template <typename T> size_t NumToStringWidth(T t, int precision = 0)
+{
+ size_t string_width = IntToDigitCount(t);
+ // Count the dot for floating point numbers
+ if (precision)
+ string_width += (precision + 1);
+ return string_width;
+}
+
+template <typename T> std::string NumToStringImplWrapper(T t, const char *fmt, int precision = 0)
+{
+ size_t string_width = NumToStringWidth(t, precision);
+ std::string s(string_width, 0x00);
+ // Allow snprintf to use std::string trailing null to detect buffer overflow
+ snprintf(const_cast<char *>(s.data()), (s.size() + 1), fmt, string_width, t);
+ return s;
+}
+#endif // FLATBUFFERS_PREFER_PRINTF
+
+// Convert an integer or floating point value to a string.
+// In contrast to std::stringstream, "char" values are
+// converted to a string of digits, and we don't use scientific notation.
+template <typename T> std::string NumToString(T t)
+{
+ // clang-format off
+
+ #ifndef FLATBUFFERS_PREFER_PRINTF
+ std::stringstream ss;
+ ss << t;
+ return ss.str();
+ #else // FLATBUFFERS_PREFER_PRINTF
+ auto v = static_cast<long long>(t);
+ return NumToStringImplWrapper(v, "%.*lld");
+ #endif // FLATBUFFERS_PREFER_PRINTF
+ // clang-format on
+}
+// Avoid char types used as character data.
+template <> inline std::string NumToString<signed char>(signed char t)
+{
+ return NumToString(static_cast<int>(t));
+}
+template <> inline std::string NumToString<unsigned char>(unsigned char t)
+{
+ return NumToString(static_cast<int>(t));
+}
+template <> inline std::string NumToString<char>(char t)
+{
+ return NumToString(static_cast<int>(t));
+}
+#if defined(FLATBUFFERS_CPP98_STL)
+template <> inline std::string NumToString<long long>(long long t)
+{
+ char buf[21]; // (log((1 << 63) - 1) / log(10)) + 2
+ snprintf(buf, sizeof(buf), "%lld", t);
+ return std::string(buf);
+}
+
+template <> inline std::string NumToString<unsigned long long>(unsigned long long t)
+{
+ char buf[22]; // (log((1 << 63) - 1) / log(10)) + 1
+ snprintf(buf, sizeof(buf), "%llu", t);
+ return std::string(buf);
+}
+#endif // defined(FLATBUFFERS_CPP98_STL)
+
+// Special versions for floats/doubles.
+template <typename T> std::string FloatToString(T t, int precision)
+{
+ // clang-format off
+
+ #ifndef FLATBUFFERS_PREFER_PRINTF
+ // to_string() prints different numbers of digits for floats depending on
+ // platform and isn't available on Android, so we use stringstream
+ std::stringstream ss;
+ // Use std::fixed to suppress scientific notation.
+ ss << std::fixed;
+ // Default precision is 6, we want that to be higher for doubles.
+ ss << std::setprecision(precision);
+ ss << t;
+ auto s = ss.str();
+ #else // FLATBUFFERS_PREFER_PRINTF
+ auto v = static_cast<double>(t);
+ auto s = NumToStringImplWrapper(v, "%0.*f", precision);
+ #endif // FLATBUFFERS_PREFER_PRINTF
+ // clang-format on
+ // Sadly, std::fixed turns "1" into "1.00000", so here we undo that.
+ auto p = s.find_last_not_of('0');
+ if (p != std::string::npos)
+ {
+ // Strip trailing zeroes. If it is a whole number, keep one zero.
+ s.resize(p + (s[p] == '.' ? 2 : 1));
+ }
+ return s;
+}
+
+template <> inline std::string NumToString<double>(double t) { return FloatToString(t, 12); }
+template <> inline std::string NumToString<float>(float t) { return FloatToString(t, 6); }
+
+// Convert an integer value to a hexadecimal string.
+// The returned string length is always xdigits long, prefixed by 0 digits.
+// For example, IntToStringHex(0x23, 8) returns the string "00000023".
+inline std::string IntToStringHex(int i, int xdigits)
+{
+ FLATBUFFERS_ASSERT(i >= 0);
+ // clang-format off
+
+ #ifndef FLATBUFFERS_PREFER_PRINTF
+ std::stringstream ss;
+ ss << std::setw(xdigits) << std::setfill('0') << std::hex << std::uppercase
+ << i;
+ return ss.str();
+ #else // FLATBUFFERS_PREFER_PRINTF
+ return NumToStringImplWrapper(i, "%.*X", xdigits);
+ #endif // FLATBUFFERS_PREFER_PRINTF
+ // clang-format on
+}
+
+// clang-format off
+// Use locale independent functions {strtod_l, strtof_l, strtoll_l, strtoull_l}.
+#if defined(FLATBUFFERS_LOCALE_INDEPENDENT) && (FLATBUFFERS_LOCALE_INDEPENDENT > 0)
+ class ClassicLocale {
+ #ifdef _MSC_VER
+ typedef _locale_t locale_type;
+ #else
+ typedef locale_t locale_type; // POSIX.1-2008 locale_t type
+ #endif
+ ClassicLocale();
+ ~ClassicLocale();
+ locale_type locale_;
+ static ClassicLocale instance_;
+ public:
+ static locale_type Get() { return instance_.locale_; }
+ };
+
+ #ifdef _MSC_VER
+ #define __strtoull_impl(s, pe, b) _strtoui64_l(s, pe, b, ClassicLocale::Get())
+ #define __strtoll_impl(s, pe, b) _strtoi64_l(s, pe, b, ClassicLocale::Get())
+ #define __strtod_impl(s, pe) _strtod_l(s, pe, ClassicLocale::Get())
+ #define __strtof_impl(s, pe) _strtof_l(s, pe, ClassicLocale::Get())
+ #else
+ #define __strtoull_impl(s, pe, b) strtoull_l(s, pe, b, ClassicLocale::Get())
+ #define __strtoll_impl(s, pe, b) strtoll_l(s, pe, b, ClassicLocale::Get())
+ #define __strtod_impl(s, pe) strtod_l(s, pe, ClassicLocale::Get())
+ #define __strtof_impl(s, pe) strtof_l(s, pe, ClassicLocale::Get())
+ #endif
+#else
+ #define __strtod_impl(s, pe) strtod(s, pe)
+ #define __strtof_impl(s, pe) static_cast<float>(strtod(s, pe))
+ #ifdef _MSC_VER
+ #define __strtoull_impl(s, pe, b) _strtoui64(s, pe, b)
+ #define __strtoll_impl(s, pe, b) _strtoi64(s, pe, b)
+ #else
+ #define __strtoull_impl(s, pe, b) strtoull(s, pe, b)
+ #define __strtoll_impl(s, pe, b) strtoll(s, pe, b)
+ #endif
+#endif
+
+inline void strtoval_impl(int64_t *val, const char *str, char **endptr,
+ int base) {
+ *val = __strtoll_impl(str, endptr, base);
+}
+
+inline void strtoval_impl(uint64_t *val, const char *str, char **endptr,
+ int base) {
+ *val = __strtoull_impl(str, endptr, base);
+}
+
+inline void strtoval_impl(double *val, const char *str, char **endptr) {
+ *val = __strtod_impl(str, endptr);
+}
+
+// UBSAN: double to float is safe if numeric_limits<float>::is_iec559 is true.
+__supress_ubsan__("float-cast-overflow")
+inline void strtoval_impl(float *val, const char *str, char **endptr) {
+ *val = __strtof_impl(str, endptr);
+}
+#undef __strtoull_impl
+#undef __strtoll_impl
+#undef __strtod_impl
+#undef __strtof_impl
+// clang-format on
+
+// Adaptor for strtoull()/strtoll().
+// Flatbuffers accepts numbers with any count of leading zeros (-009 is -9),
+// while strtoll with base=0 interprets first leading zero as octal prefix.
+// In future, it is possible to add prefixed 0b0101.
+// 1) Checks errno code for overflow condition (out of range).
+// 2) If base <= 0, function try to detect base of number by prefix.
+//
+// Return value (like strtoull and strtoll, but reject partial result):
+// - If successful, an integer value corresponding to the str is returned.
+// - If full string conversion can't be performed, 0 is returned.
+// - If the converted value falls out of range of corresponding return type, a
+// range error occurs. In this case value MAX(T)/MIN(T) is returned.
+template <typename T>
+inline bool StringToIntegerImpl(T *val, const char *const str, const int base = 0,
+ const bool check_errno = true)
+{
+ // T is int64_t or uint64_T
+ FLATBUFFERS_ASSERT(str);
+ if (base <= 0)
+ {
+ auto s = str;
+ while (*s && !is_digit(*s))
+ s++;
+ if (s[0] == '0' && is_alpha_char(s[1], 'X'))
+ return StringToIntegerImpl(val, str, 16, check_errno);
+ // if a prefix not match, try base=10
+ return StringToIntegerImpl(val, str, 10, check_errno);
+ }
+ else
+ {
+ if (check_errno)
+ errno = 0; // clear thread-local errno
+ auto endptr = str;
+ strtoval_impl(val, str, const_cast<char **>(&endptr), base);
+ if ((*endptr != '\0') || (endptr == str))
+ {
+ *val = 0; // erase partial result
+ return false; // invalid string
+ }
+ // errno is out-of-range, return MAX/MIN
+ if (check_errno && errno)
+ return false;
+ return true;
+ }
+}
+
+template <typename T> inline bool StringToFloatImpl(T *val, const char *const str)
+{
+ // Type T must be either float or double.
+ FLATBUFFERS_ASSERT(str && val);
+ auto end = str;
+ strtoval_impl(val, str, const_cast<char **>(&end));
+ auto done = (end != str) && (*end == '\0');
+ if (!done)
+ *val = 0; // erase partial result
+ return done;
+}
+
+// Convert a string to an instance of T.
+// Return value (matched with StringToInteger64Impl and strtod):
+// - If successful, a numeric value corresponding to the str is returned.
+// - If full string conversion can't be performed, 0 is returned.
+// - If the converted value falls out of range of corresponding return type, a
+// range error occurs. In this case value MAX(T)/MIN(T) is returned.
+template <typename T> inline bool StringToNumber(const char *s, T *val)
+{
+ // Assert on `unsigned long` and `signed long` on LP64.
+ // If it is necessary, it could be solved with flatbuffers::enable_if<B,T>.
+ static_assert(sizeof(T) < sizeof(int64_t), "unexpected type T");
+ FLATBUFFERS_ASSERT(s && val);
+ int64_t i64;
+ // The errno check isn't needed, will return MAX/MIN on overflow.
+ if (StringToIntegerImpl(&i64, s, 0, false))
+ {
+ const int64_t max = (flatbuffers::numeric_limits<T>::max)();
+ const int64_t min = flatbuffers::numeric_limits<T>::lowest();
+ if (i64 > max)
+ {
+ *val = static_cast<T>(max);
+ return false;
+ }
+ if (i64 < min)
+ {
+ // For unsigned types return max to distinguish from
+ // "no conversion can be performed" when 0 is returned.
+ *val = static_cast<T>(flatbuffers::is_unsigned<T>::value ? max : min);
+ return false;
+ }
+ *val = static_cast<T>(i64);
+ return true;
+ }
+ *val = 0;
+ return false;
+}
+
+template <> inline bool StringToNumber<int64_t>(const char *str, int64_t *val)
+{
+ return StringToIntegerImpl(val, str);
+}
+
+template <> inline bool StringToNumber<uint64_t>(const char *str, uint64_t *val)
+{
+ if (!StringToIntegerImpl(val, str))
+ return false;
+ // The strtoull accepts negative numbers:
+ // If the minus sign was part of the input sequence, the numeric value
+ // calculated from the sequence of digits is negated as if by unary minus
+ // in the result type, which applies unsigned integer wraparound rules.
+ // Fix this behaviour (except -0).
+ if (*val)
+ {
+ auto s = str;
+ while (*s && !is_digit(*s))
+ s++;
+ s = (s > str) ? (s - 1) : s; // step back to one symbol
+ if (*s == '-')
+ {
+ // For unsigned types return the max to distinguish from
+ // "no conversion can be performed".
+ *val = (flatbuffers::numeric_limits<uint64_t>::max)();
+ return false;
+ }
+ }
+ return true;
+}
+
+template <> inline bool StringToNumber(const char *s, float *val)
+{
+ return StringToFloatImpl(val, s);
+}
+
+template <> inline bool StringToNumber(const char *s, double *val)
+{
+ return StringToFloatImpl(val, s);
+}
+
+inline int64_t StringToInt(const char *s, int base = 10)
+{
+ int64_t val;
+ return StringToIntegerImpl(&val, s, base) ? val : 0;
+}
+
+inline uint64_t StringToUInt(const char *s, int base = 10)
+{
+ uint64_t val;
+ return StringToIntegerImpl(&val, s, base) ? val : 0;
+}
+
+typedef bool (*LoadFileFunction)(const char *filename, bool binary, std::string *dest);
+typedef bool (*FileExistsFunction)(const char *filename);
+
+LoadFileFunction SetLoadFileFunction(LoadFileFunction load_file_function);
+
+FileExistsFunction SetFileExistsFunction(FileExistsFunction file_exists_function);
+
+// Check if file "name" exists.
+bool FileExists(const char *name);
+
+// Check if "name" exists and it is also a directory.
+bool DirExists(const char *name);
+
+// Load file "name" into "buf" returning true if successful
+// false otherwise. If "binary" is false data is read
+// using ifstream's text mode, otherwise data is read with
+// no transcoding.
+bool LoadFile(const char *name, bool binary, std::string *buf);
+
+// Save data "buf" of length "len" bytes into a file
+// "name" returning true if successful, false otherwise.
+// If "binary" is false data is written using ifstream's
+// text mode, otherwise data is written with no
+// transcoding.
+bool SaveFile(const char *name, const char *buf, size_t len, bool binary);
+
+// Save data "buf" into file "name" returning true if
+// successful, false otherwise. If "binary" is false
+// data is written using ifstream's text mode, otherwise
+// data is written with no transcoding.
+inline bool SaveFile(const char *name, const std::string &buf, bool binary)
+{
+ return SaveFile(name, buf.c_str(), buf.size(), binary);
+}
+
+// Functionality for minimalistic portable path handling.
+
+// The functions below behave correctly regardless of whether posix ('/') or
+// Windows ('/' or '\\') separators are used.
+
+// Any new separators inserted are always posix.
+FLATBUFFERS_CONSTEXPR char kPathSeparator = '/';
+
+// Returns the path with the extension, if any, removed.
+std::string StripExtension(const std::string &filepath);
+
+// Returns the extension, if any.
+std::string GetExtension(const std::string &filepath);
+
+// Return the last component of the path, after the last separator.
+std::string StripPath(const std::string &filepath);
+
+// Strip the last component of the path + separator.
+std::string StripFileName(const std::string &filepath);
+
+// Concatenates a path with a filename, regardless of whether the path
+// ends in a separator or not.
+std::string ConCatPathFileName(const std::string &path, const std::string &filename);
+
+// Replaces any '\\' separators with '/'
+std::string PosixPath(const char *path);
+
+// This function ensure a directory exists, by recursively
+// creating dirs for any parts of the path that don't exist yet.
+void EnsureDirExists(const std::string &filepath);
+
+// Obtains the absolute path from any other path.
+// Returns the input path if the absolute path couldn't be resolved.
+std::string AbsolutePath(const std::string &filepath);
+
+// To and from UTF-8 unicode conversion functions
+
+// Convert a unicode code point into a UTF-8 representation by appending it
+// to a string. Returns the number of bytes generated.
+inline int ToUTF8(uint32_t ucc, std::string *out)
+{
+ FLATBUFFERS_ASSERT(!(ucc & 0x80000000)); // Top bit can't be set.
+ // 6 possible encodings: http://en.wikipedia.org/wiki/UTF-8
+ for (int i = 0; i < 6; i++)
+ {
+ // Max bits this encoding can represent.
+ uint32_t max_bits = 6 + i * 5 + static_cast<int>(!i);
+ if (ucc < (1u << max_bits))
+ { // does it fit?
+ // Remaining bits not encoded in the first byte, store 6 bits each
+ uint32_t remain_bits = i * 6;
+ // Store first byte:
+ (*out) += static_cast<char>((0xFE << (max_bits - remain_bits)) | (ucc >> remain_bits));
+ // Store remaining bytes:
+ for (int j = i - 1; j >= 0; j--)
+ {
+ (*out) += static_cast<char>(((ucc >> (j * 6)) & 0x3F) | 0x80);
+ }
+ return i + 1; // Return the number of bytes added.
+ }
+ }
+ FLATBUFFERS_ASSERT(0); // Impossible to arrive here.
+ return -1;
+}
+
+// Converts whatever prefix of the incoming string corresponds to a valid
+// UTF-8 sequence into a unicode code. The incoming pointer will have been
+// advanced past all bytes parsed.
+// returns -1 upon corrupt UTF-8 encoding (ignore the incoming pointer in
+// this case).
+inline int FromUTF8(const char **in)
+{
+ int len = 0;
+ // Count leading 1 bits.
+ for (int mask = 0x80; mask >= 0x04; mask >>= 1)
+ {
+ if (**in & mask)
+ {
+ len++;
+ }
+ else
+ {
+ break;
+ }
+ }
+ if ((static_cast<unsigned char>(**in) << len) & 0x80)
+ return -1; // Bit after leading 1's must be 0.
+ if (!len)
+ return *(*in)++;
+ // UTF-8 encoded values with a length are between 2 and 4 bytes.
+ if (len < 2 || len > 4)
+ {
+ return -1;
+ }
+ // Grab initial bits of the code.
+ int ucc = *(*in)++ & ((1 << (7 - len)) - 1);
+ for (int i = 0; i < len - 1; i++)
+ {
+ if ((**in & 0xC0) != 0x80)
+ return -1; // Upper bits must 1 0.
+ ucc <<= 6;
+ ucc |= *(*in)++ & 0x3F; // Grab 6 more bits of the code.
+ }
+ // UTF-8 cannot encode values between 0xD800 and 0xDFFF (reserved for
+ // UTF-16 surrogate pairs).
+ if (ucc >= 0xD800 && ucc <= 0xDFFF)
+ {
+ return -1;
+ }
+ // UTF-8 must represent code points in their shortest possible encoding.
+ switch (len)
+ {
+ case 2:
+ // Two bytes of UTF-8 can represent code points from U+0080 to U+07FF.
+ if (ucc < 0x0080 || ucc > 0x07FF)
+ {
+ return -1;
+ }
+ break;
+ case 3:
+ // Three bytes of UTF-8 can represent code points from U+0800 to U+FFFF.
+ if (ucc < 0x0800 || ucc > 0xFFFF)
+ {
+ return -1;
+ }
+ break;
+ case 4:
+ // Four bytes of UTF-8 can represent code points from U+10000 to U+10FFFF.
+ if (ucc < 0x10000 || ucc > 0x10FFFF)
+ {
+ return -1;
+ }
+ break;
+ }
+ return ucc;
+}
+
+#ifndef FLATBUFFERS_PREFER_PRINTF
+// Wraps a string to a maximum length, inserting new lines where necessary. Any
+// existing whitespace will be collapsed down to a single space. A prefix or
+// suffix can be provided, which will be inserted before or after a wrapped
+// line, respectively.
+inline std::string WordWrap(const std::string in, size_t max_length,
+ const std::string wrapped_line_prefix,
+ const std::string wrapped_line_suffix)
+{
+ std::istringstream in_stream(in);
+ std::string wrapped, line, word;
+
+ in_stream >> word;
+ line = word;
+
+ while (in_stream >> word)
+ {
+ if ((line.length() + 1 + word.length() + wrapped_line_suffix.length()) < max_length)
+ {
+ line += " " + word;
+ }
+ else
+ {
+ wrapped += line + wrapped_line_suffix + "\n";
+ line = wrapped_line_prefix + word;
+ }
+ }
+ wrapped += line;
+
+ return wrapped;
+}
+#endif // !FLATBUFFERS_PREFER_PRINTF
+
+inline bool EscapeString(const char *s, size_t length, std::string *_text, bool allow_non_utf8,
+ bool natural_utf8)
+{
+ std::string &text = *_text;
+ text += "\"";
+ for (uoffset_t i = 0; i < length; i++)
+ {
+ char c = s[i];
+ switch (c)
+ {
+ case '\n':
+ text += "\\n";
+ break;
+ case '\t':
+ text += "\\t";
+ break;
+ case '\r':
+ text += "\\r";
+ break;
+ case '\b':
+ text += "\\b";
+ break;
+ case '\f':
+ text += "\\f";
+ break;
+ case '\"':
+ text += "\\\"";
+ break;
+ case '\\':
+ text += "\\\\";
+ break;
+ default:
+ if (c >= ' ' && c <= '~')
+ {
+ text += c;
+ }
+ else
+ {
+ // Not printable ASCII data. Let's see if it's valid UTF-8 first:
+ const char *utf8 = s + i;
+ int ucc = FromUTF8(&utf8);
+ if (ucc < 0)
+ {
+ if (allow_non_utf8)
+ {
+ text += "\\x";
+ text += IntToStringHex(static_cast<uint8_t>(c), 2);
+ }
+ else
+ {
+ // There are two cases here:
+ //
+ // 1) We reached here by parsing an IDL file. In that case,
+ // we previously checked for non-UTF-8, so we shouldn't reach
+ // here.
+ //
+ // 2) We reached here by someone calling GenerateText()
+ // on a previously-serialized flatbuffer. The data might have
+ // non-UTF-8 Strings, or might be corrupt.
+ //
+ // In both cases, we have to give up and inform the caller
+ // they have no JSON.
+ return false;
+ }
+ }
+ else
+ {
+ if (natural_utf8)
+ {
+ // utf8 points to past all utf-8 bytes parsed
+ text.append(s + i, static_cast<size_t>(utf8 - s - i));
+ }
+ else if (ucc <= 0xFFFF)
+ {
+ // Parses as Unicode within JSON's \uXXXX range, so use that.
+ text += "\\u";
+ text += IntToStringHex(ucc, 4);
+ }
+ else if (ucc <= 0x10FFFF)
+ {
+ // Encode Unicode SMP values to a surrogate pair using two \u
+ // escapes.
+ uint32_t base = ucc - 0x10000;
+ auto high_surrogate = (base >> 10) + 0xD800;
+ auto low_surrogate = (base & 0x03FF) + 0xDC00;
+ text += "\\u";
+ text += IntToStringHex(high_surrogate, 4);
+ text += "\\u";
+ text += IntToStringHex(low_surrogate, 4);
+ }
+ // Skip past characters recognized.
+ i = static_cast<uoffset_t>(utf8 - s - 1);
+ }
+ }
+ break;
+ }
+ }
+ text += "\"";
+ return true;
+}
+
+inline std::string BufferToHexText(const void *buffer, size_t buffer_size, size_t max_length,
+ const std::string &wrapped_line_prefix,
+ const std::string &wrapped_line_suffix)
+{
+ std::string text = wrapped_line_prefix;
+ size_t start_offset = 0;
+ const char *s = reinterpret_cast<const char *>(buffer);
+ for (size_t i = 0; s && i < buffer_size; i++)
+ {
+ // Last iteration or do we have more?
+ bool have_more = i + 1 < buffer_size;
+ text += "0x";
+ text += IntToStringHex(static_cast<uint8_t>(s[i]), 2);
+ if (have_more)
+ {
+ text += ',';
+ }
+ // If we have more to process and we reached max_length
+ if (have_more && text.size() + wrapped_line_suffix.size() >= start_offset + max_length)
+ {
+ text += wrapped_line_suffix;
+ text += '\n';
+ start_offset = text.size();
+ text += wrapped_line_prefix;
+ }
+ }
+ text += wrapped_line_suffix;
+ return text;
+}
+
+// Remove paired quotes in a string: "text"|'text' -> text.
+std::string RemoveStringQuotes(const std::string &s);
+
+// Change th global C-locale to locale with name <locale_name>.
+// Returns an actual locale name in <_value>, useful if locale_name is "" or
+// null.
+bool SetGlobalTestLocale(const char *locale_name, std::string *_value = nullptr);
+
+// Read (or test) a value of environment variable.
+bool ReadEnvironmentVariable(const char *var_name, std::string *_value = nullptr);
+
+// MSVC specific: Send all assert reports to STDOUT to prevent CI hangs.
+void SetupDefaultCRTReportMode();
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_UTIL_H_
diff --git a/onert-micro/externals/gen/circle-generated/circle/schema_generated.h b/onert-micro/externals/gen/circle-generated/circle/schema_generated.h
new file mode 100644
index 000000000..2531319f9
--- /dev/null
+++ b/onert-micro/externals/gen/circle-generated/circle/schema_generated.h
@@ -0,0 +1,24984 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// automatically generated by the FlatBuffers compiler, do not modify
+
+#ifndef FLATBUFFERS_GENERATED_SCHEMA_CIRCLE_H_
+#define FLATBUFFERS_GENERATED_SCHEMA_CIRCLE_H_
+
+#include "flatbuffers/flatbuffers.h"
+
+namespace circle
+{
+
+struct CustomQuantization;
+struct CustomQuantizationBuilder;
+struct CustomQuantizationT;
+
+struct QuantizationParameters;
+struct QuantizationParametersBuilder;
+struct QuantizationParametersT;
+
+struct Int32Vector;
+struct Int32VectorBuilder;
+struct Int32VectorT;
+
+struct Uint16Vector;
+struct Uint16VectorBuilder;
+struct Uint16VectorT;
+
+struct Uint8Vector;
+struct Uint8VectorBuilder;
+struct Uint8VectorT;
+
+struct DimensionMetadata;
+struct DimensionMetadataBuilder;
+struct DimensionMetadataT;
+
+struct SparsityParameters;
+struct SparsityParametersBuilder;
+struct SparsityParametersT;
+
+struct Tensor;
+struct TensorBuilder;
+struct TensorT;
+
+struct Conv2DOptions;
+struct Conv2DOptionsBuilder;
+struct Conv2DOptionsT;
+
+struct Conv3DOptions;
+struct Conv3DOptionsBuilder;
+struct Conv3DOptionsT;
+
+struct Pool2DOptions;
+struct Pool2DOptionsBuilder;
+struct Pool2DOptionsT;
+
+struct DepthwiseConv2DOptions;
+struct DepthwiseConv2DOptionsBuilder;
+struct DepthwiseConv2DOptionsT;
+
+struct ConcatEmbeddingsOptions;
+struct ConcatEmbeddingsOptionsBuilder;
+struct ConcatEmbeddingsOptionsT;
+
+struct LSHProjectionOptions;
+struct LSHProjectionOptionsBuilder;
+struct LSHProjectionOptionsT;
+
+struct SVDFOptions;
+struct SVDFOptionsBuilder;
+struct SVDFOptionsT;
+
+struct RNNOptions;
+struct RNNOptionsBuilder;
+struct RNNOptionsT;
+
+struct SequenceRNNOptions;
+struct SequenceRNNOptionsBuilder;
+struct SequenceRNNOptionsT;
+
+struct BidirectionalSequenceRNNOptions;
+struct BidirectionalSequenceRNNOptionsBuilder;
+struct BidirectionalSequenceRNNOptionsT;
+
+struct FullyConnectedOptions;
+struct FullyConnectedOptionsBuilder;
+struct FullyConnectedOptionsT;
+
+struct SoftmaxOptions;
+struct SoftmaxOptionsBuilder;
+struct SoftmaxOptionsT;
+
+struct ConcatenationOptions;
+struct ConcatenationOptionsBuilder;
+struct ConcatenationOptionsT;
+
+struct AddOptions;
+struct AddOptionsBuilder;
+struct AddOptionsT;
+
+struct MulOptions;
+struct MulOptionsBuilder;
+struct MulOptionsT;
+
+struct L2NormOptions;
+struct L2NormOptionsBuilder;
+struct L2NormOptionsT;
+
+struct LocalResponseNormalizationOptions;
+struct LocalResponseNormalizationOptionsBuilder;
+struct LocalResponseNormalizationOptionsT;
+
+struct LSTMOptions;
+struct LSTMOptionsBuilder;
+struct LSTMOptionsT;
+
+struct UnidirectionalSequenceLSTMOptions;
+struct UnidirectionalSequenceLSTMOptionsBuilder;
+struct UnidirectionalSequenceLSTMOptionsT;
+
+struct BidirectionalSequenceLSTMOptions;
+struct BidirectionalSequenceLSTMOptionsBuilder;
+struct BidirectionalSequenceLSTMOptionsT;
+
+struct ResizeBilinearOptions;
+struct ResizeBilinearOptionsBuilder;
+struct ResizeBilinearOptionsT;
+
+struct ResizeNearestNeighborOptions;
+struct ResizeNearestNeighborOptionsBuilder;
+struct ResizeNearestNeighborOptionsT;
+
+struct CallOptions;
+struct CallOptionsBuilder;
+struct CallOptionsT;
+
+struct PadOptions;
+struct PadOptionsBuilder;
+struct PadOptionsT;
+
+struct PadV2Options;
+struct PadV2OptionsBuilder;
+struct PadV2OptionsT;
+
+struct ReshapeOptions;
+struct ReshapeOptionsBuilder;
+struct ReshapeOptionsT;
+
+struct SpaceToBatchNDOptions;
+struct SpaceToBatchNDOptionsBuilder;
+struct SpaceToBatchNDOptionsT;
+
+struct BatchToSpaceNDOptions;
+struct BatchToSpaceNDOptionsBuilder;
+struct BatchToSpaceNDOptionsT;
+
+struct SkipGramOptions;
+struct SkipGramOptionsBuilder;
+struct SkipGramOptionsT;
+
+struct SpaceToDepthOptions;
+struct SpaceToDepthOptionsBuilder;
+struct SpaceToDepthOptionsT;
+
+struct DepthToSpaceOptions;
+struct DepthToSpaceOptionsBuilder;
+struct DepthToSpaceOptionsT;
+
+struct SubOptions;
+struct SubOptionsBuilder;
+struct SubOptionsT;
+
+struct DivOptions;
+struct DivOptionsBuilder;
+struct DivOptionsT;
+
+struct TopKV2Options;
+struct TopKV2OptionsBuilder;
+struct TopKV2OptionsT;
+
+struct EmbeddingLookupSparseOptions;
+struct EmbeddingLookupSparseOptionsBuilder;
+struct EmbeddingLookupSparseOptionsT;
+
+struct GatherOptions;
+struct GatherOptionsBuilder;
+struct GatherOptionsT;
+
+struct TransposeOptions;
+struct TransposeOptionsBuilder;
+struct TransposeOptionsT;
+
+struct ExpOptions;
+struct ExpOptionsBuilder;
+struct ExpOptionsT;
+
+struct CosOptions;
+struct CosOptionsBuilder;
+struct CosOptionsT;
+
+struct ReducerOptions;
+struct ReducerOptionsBuilder;
+struct ReducerOptionsT;
+
+struct SqueezeOptions;
+struct SqueezeOptionsBuilder;
+struct SqueezeOptionsT;
+
+struct SplitOptions;
+struct SplitOptionsBuilder;
+struct SplitOptionsT;
+
+struct SplitVOptions;
+struct SplitVOptionsBuilder;
+struct SplitVOptionsT;
+
+struct StridedSliceOptions;
+struct StridedSliceOptionsBuilder;
+struct StridedSliceOptionsT;
+
+struct LogSoftmaxOptions;
+struct LogSoftmaxOptionsBuilder;
+struct LogSoftmaxOptionsT;
+
+struct CastOptions;
+struct CastOptionsBuilder;
+struct CastOptionsT;
+
+struct DequantizeOptions;
+struct DequantizeOptionsBuilder;
+struct DequantizeOptionsT;
+
+struct MaximumMinimumOptions;
+struct MaximumMinimumOptionsBuilder;
+struct MaximumMinimumOptionsT;
+
+struct TileOptions;
+struct TileOptionsBuilder;
+struct TileOptionsT;
+
+struct ArgMaxOptions;
+struct ArgMaxOptionsBuilder;
+struct ArgMaxOptionsT;
+
+struct ArgMinOptions;
+struct ArgMinOptionsBuilder;
+struct ArgMinOptionsT;
+
+struct GreaterOptions;
+struct GreaterOptionsBuilder;
+struct GreaterOptionsT;
+
+struct GreaterEqualOptions;
+struct GreaterEqualOptionsBuilder;
+struct GreaterEqualOptionsT;
+
+struct LessOptions;
+struct LessOptionsBuilder;
+struct LessOptionsT;
+
+struct LessEqualOptions;
+struct LessEqualOptionsBuilder;
+struct LessEqualOptionsT;
+
+struct NegOptions;
+struct NegOptionsBuilder;
+struct NegOptionsT;
+
+struct SelectOptions;
+struct SelectOptionsBuilder;
+struct SelectOptionsT;
+
+struct SliceOptions;
+struct SliceOptionsBuilder;
+struct SliceOptionsT;
+
+struct TransposeConvOptions;
+struct TransposeConvOptionsBuilder;
+struct TransposeConvOptionsT;
+
+struct ExpandDimsOptions;
+struct ExpandDimsOptionsBuilder;
+struct ExpandDimsOptionsT;
+
+struct SparseToDenseOptions;
+struct SparseToDenseOptionsBuilder;
+struct SparseToDenseOptionsT;
+
+struct EqualOptions;
+struct EqualOptionsBuilder;
+struct EqualOptionsT;
+
+struct NotEqualOptions;
+struct NotEqualOptionsBuilder;
+struct NotEqualOptionsT;
+
+struct ShapeOptions;
+struct ShapeOptionsBuilder;
+struct ShapeOptionsT;
+
+struct RankOptions;
+struct RankOptionsBuilder;
+struct RankOptionsT;
+
+struct PowOptions;
+struct PowOptionsBuilder;
+struct PowOptionsT;
+
+struct FakeQuantOptions;
+struct FakeQuantOptionsBuilder;
+struct FakeQuantOptionsT;
+
+struct PackOptions;
+struct PackOptionsBuilder;
+struct PackOptionsT;
+
+struct LogicalOrOptions;
+struct LogicalOrOptionsBuilder;
+struct LogicalOrOptionsT;
+
+struct OneHotOptions;
+struct OneHotOptionsBuilder;
+struct OneHotOptionsT;
+
+struct AbsOptions;
+struct AbsOptionsBuilder;
+struct AbsOptionsT;
+
+struct HardSwishOptions;
+struct HardSwishOptionsBuilder;
+struct HardSwishOptionsT;
+
+struct LogicalAndOptions;
+struct LogicalAndOptionsBuilder;
+struct LogicalAndOptionsT;
+
+struct LogicalNotOptions;
+struct LogicalNotOptionsBuilder;
+struct LogicalNotOptionsT;
+
+struct UnpackOptions;
+struct UnpackOptionsBuilder;
+struct UnpackOptionsT;
+
+struct FloorDivOptions;
+struct FloorDivOptionsBuilder;
+struct FloorDivOptionsT;
+
+struct SquareOptions;
+struct SquareOptionsBuilder;
+struct SquareOptionsT;
+
+struct ZerosLikeOptions;
+struct ZerosLikeOptionsBuilder;
+struct ZerosLikeOptionsT;
+
+struct FillOptions;
+struct FillOptionsBuilder;
+struct FillOptionsT;
+
+struct FloorModOptions;
+struct FloorModOptionsBuilder;
+struct FloorModOptionsT;
+
+struct RangeOptions;
+struct RangeOptionsBuilder;
+struct RangeOptionsT;
+
+struct LeakyReluOptions;
+struct LeakyReluOptionsBuilder;
+struct LeakyReluOptionsT;
+
+struct SquaredDifferenceOptions;
+struct SquaredDifferenceOptionsBuilder;
+struct SquaredDifferenceOptionsT;
+
+struct MirrorPadOptions;
+struct MirrorPadOptionsBuilder;
+struct MirrorPadOptionsT;
+
+struct UniqueOptions;
+struct UniqueOptionsBuilder;
+struct UniqueOptionsT;
+
+struct ReverseV2Options;
+struct ReverseV2OptionsBuilder;
+struct ReverseV2OptionsT;
+
+struct AddNOptions;
+struct AddNOptionsBuilder;
+struct AddNOptionsT;
+
+struct GatherNdOptions;
+struct GatherNdOptionsBuilder;
+struct GatherNdOptionsT;
+
+struct WhereOptions;
+struct WhereOptionsBuilder;
+struct WhereOptionsT;
+
+struct ReverseSequenceOptions;
+struct ReverseSequenceOptionsBuilder;
+struct ReverseSequenceOptionsT;
+
+struct MatrixDiagOptions;
+struct MatrixDiagOptionsBuilder;
+struct MatrixDiagOptionsT;
+
+struct QuantizeOptions;
+struct QuantizeOptionsBuilder;
+struct QuantizeOptionsT;
+
+struct MatrixSetDiagOptions;
+struct MatrixSetDiagOptionsBuilder;
+struct MatrixSetDiagOptionsT;
+
+struct IfOptions;
+struct IfOptionsBuilder;
+struct IfOptionsT;
+
+struct CallOnceOptions;
+struct CallOnceOptionsBuilder;
+struct CallOnceOptionsT;
+
+struct WhileOptions;
+struct WhileOptionsBuilder;
+struct WhileOptionsT;
+
+struct NonMaxSuppressionV4Options;
+struct NonMaxSuppressionV4OptionsBuilder;
+struct NonMaxSuppressionV4OptionsT;
+
+struct NonMaxSuppressionV5Options;
+struct NonMaxSuppressionV5OptionsBuilder;
+struct NonMaxSuppressionV5OptionsT;
+
+struct ScatterNdOptions;
+struct ScatterNdOptionsBuilder;
+struct ScatterNdOptionsT;
+
+struct SelectV2Options;
+struct SelectV2OptionsBuilder;
+struct SelectV2OptionsT;
+
+struct DensifyOptions;
+struct DensifyOptionsBuilder;
+struct DensifyOptionsT;
+
+struct SegmentSumOptions;
+struct SegmentSumOptionsBuilder;
+struct SegmentSumOptionsT;
+
+struct BatchMatMulOptions;
+struct BatchMatMulOptionsBuilder;
+struct BatchMatMulOptionsT;
+
+struct CumsumOptions;
+struct CumsumOptionsBuilder;
+struct CumsumOptionsT;
+
+struct BroadcastToOptions;
+struct BroadcastToOptionsBuilder;
+struct BroadcastToOptionsT;
+
+struct Rfft2dOptions;
+struct Rfft2dOptionsBuilder;
+struct Rfft2dOptionsT;
+
+struct HashtableOptions;
+struct HashtableOptionsBuilder;
+struct HashtableOptionsT;
+
+struct HashtableFindOptions;
+struct HashtableFindOptionsBuilder;
+struct HashtableFindOptionsT;
+
+struct HashtableImportOptions;
+struct HashtableImportOptionsBuilder;
+struct HashtableImportOptionsT;
+
+struct HashtableSizeOptions;
+struct HashtableSizeOptionsBuilder;
+struct HashtableSizeOptionsT;
+
+struct VarHandleOptions;
+struct VarHandleOptionsBuilder;
+struct VarHandleOptionsT;
+
+struct ReadVariableOptions;
+struct ReadVariableOptionsBuilder;
+struct ReadVariableOptionsT;
+
+struct AssignVariableOptions;
+struct AssignVariableOptionsBuilder;
+struct AssignVariableOptionsT;
+
+struct RandomOptions;
+struct RandomOptionsBuilder;
+struct RandomOptionsT;
+
+struct BCQGatherOptions;
+struct BCQGatherOptionsBuilder;
+struct BCQGatherOptionsT;
+
+struct BCQFullyConnectedOptions;
+struct BCQFullyConnectedOptionsBuilder;
+struct BCQFullyConnectedOptionsT;
+
+struct InstanceNormOptions;
+struct InstanceNormOptionsBuilder;
+struct InstanceNormOptionsT;
+
+struct OperatorCode;
+struct OperatorCodeBuilder;
+struct OperatorCodeT;
+
+struct Operator;
+struct OperatorBuilder;
+struct OperatorT;
+
+struct SubGraph;
+struct SubGraphBuilder;
+struct SubGraphT;
+
+struct Buffer;
+struct BufferBuilder;
+struct BufferT;
+
+struct Metadata;
+struct MetadataBuilder;
+struct MetadataT;
+
+struct TensorMap;
+struct TensorMapBuilder;
+struct TensorMapT;
+
+struct SignatureDef;
+struct SignatureDefBuilder;
+struct SignatureDefT;
+
+struct Model;
+struct ModelBuilder;
+struct ModelT;
+
+enum TensorType : int8_t
+{
+ TensorType_FLOAT32 = 0,
+ TensorType_FLOAT16 = 1,
+ TensorType_INT32 = 2,
+ TensorType_UINT8 = 3,
+ TensorType_INT64 = 4,
+ TensorType_STRING = 5,
+ TensorType_BOOL = 6,
+ TensorType_INT16 = 7,
+ TensorType_COMPLEX64 = 8,
+ TensorType_INT8 = 9,
+ TensorType_FLOAT64 = 10,
+ TensorType_COMPLEX128 = 11,
+ TensorType_UINT64 = 12,
+ TensorType_RESOURCE = 13,
+ TensorType_VARIANT = 14,
+ TensorType_UINT32 = 15,
+ TensorType_MIN = TensorType_FLOAT32,
+ TensorType_MAX = TensorType_UINT32
+};
+
+inline const TensorType (&EnumValuesTensorType())[16]
+{
+ static const TensorType values[] = {
+ TensorType_FLOAT32, TensorType_FLOAT16, TensorType_INT32, TensorType_UINT8,
+ TensorType_INT64, TensorType_STRING, TensorType_BOOL, TensorType_INT16,
+ TensorType_COMPLEX64, TensorType_INT8, TensorType_FLOAT64, TensorType_COMPLEX128,
+ TensorType_UINT64, TensorType_RESOURCE, TensorType_VARIANT, TensorType_UINT32};
+ return values;
+}
+
+inline const char *const *EnumNamesTensorType()
+{
+ static const char *const names[17] = {"FLOAT32", "FLOAT16", "INT32", "UINT8", "INT64",
+ "STRING", "BOOL", "INT16", "COMPLEX64", "INT8",
+ "FLOAT64", "COMPLEX128", "UINT64", "RESOURCE", "VARIANT",
+ "UINT32", nullptr};
+ return names;
+}
+
+inline const char *EnumNameTensorType(TensorType e)
+{
+ if (flatbuffers::IsOutRange(e, TensorType_FLOAT32, TensorType_UINT32))
+ return "";
+ const size_t index = static_cast<size_t>(e);
+ return EnumNamesTensorType()[index];
+}
+
+enum QuantizationDetails : uint8_t
+{
+ QuantizationDetails_NONE = 0,
+ QuantizationDetails_CustomQuantization = 1,
+ QuantizationDetails_MIN = QuantizationDetails_NONE,
+ QuantizationDetails_MAX = QuantizationDetails_CustomQuantization
+};
+
+inline const QuantizationDetails (&EnumValuesQuantizationDetails())[2]
+{
+ static const QuantizationDetails values[] = {QuantizationDetails_NONE,
+ QuantizationDetails_CustomQuantization};
+ return values;
+}
+
+inline const char *const *EnumNamesQuantizationDetails()
+{
+ static const char *const names[3] = {"NONE", "CustomQuantization", nullptr};
+ return names;
+}
+
+inline const char *EnumNameQuantizationDetails(QuantizationDetails e)
+{
+ if (flatbuffers::IsOutRange(e, QuantizationDetails_NONE, QuantizationDetails_CustomQuantization))
+ return "";
+ const size_t index = static_cast<size_t>(e);
+ return EnumNamesQuantizationDetails()[index];
+}
+
+template <typename T> struct QuantizationDetailsTraits
+{
+ static const QuantizationDetails enum_value = QuantizationDetails_NONE;
+};
+
+template <> struct QuantizationDetailsTraits<circle::CustomQuantization>
+{
+ static const QuantizationDetails enum_value = QuantizationDetails_CustomQuantization;
+};
+
+struct QuantizationDetailsUnion
+{
+ QuantizationDetails type;
+ void *value;
+
+ QuantizationDetailsUnion() : type(QuantizationDetails_NONE), value(nullptr) {}
+ QuantizationDetailsUnion(QuantizationDetailsUnion &&u) FLATBUFFERS_NOEXCEPT
+ : type(QuantizationDetails_NONE),
+ value(nullptr)
+ {
+ std::swap(type, u.type);
+ std::swap(value, u.value);
+ }
+ QuantizationDetailsUnion(const QuantizationDetailsUnion &);
+ QuantizationDetailsUnion &operator=(const QuantizationDetailsUnion &u)
+ {
+ QuantizationDetailsUnion t(u);
+ std::swap(type, t.type);
+ std::swap(value, t.value);
+ return *this;
+ }
+ QuantizationDetailsUnion &operator=(QuantizationDetailsUnion &&u) FLATBUFFERS_NOEXCEPT
+ {
+ std::swap(type, u.type);
+ std::swap(value, u.value);
+ return *this;
+ }
+ ~QuantizationDetailsUnion() { Reset(); }
+
+ void Reset();
+
+#ifndef FLATBUFFERS_CPP98_STL
+ template <typename T> void Set(T &&val)
+ {
+ using RT = typename std::remove_reference<T>::type;
+ Reset();
+ type = QuantizationDetailsTraits<typename RT::TableType>::enum_value;
+ if (type != QuantizationDetails_NONE)
+ {
+ value = new RT(std::forward<T>(val));
+ }
+ }
+#endif // FLATBUFFERS_CPP98_STL
+
+ static void *UnPack(const void *obj, QuantizationDetails type,
+ const flatbuffers::resolver_function_t *resolver);
+ flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr) const;
+
+ circle::CustomQuantizationT *AsCustomQuantization()
+ {
+ return type == QuantizationDetails_CustomQuantization
+ ? reinterpret_cast<circle::CustomQuantizationT *>(value)
+ : nullptr;
+ }
+ const circle::CustomQuantizationT *AsCustomQuantization() const
+ {
+ return type == QuantizationDetails_CustomQuantization
+ ? reinterpret_cast<const circle::CustomQuantizationT *>(value)
+ : nullptr;
+ }
+};
+
+bool VerifyQuantizationDetails(flatbuffers::Verifier &verifier, const void *obj,
+ QuantizationDetails type);
+bool VerifyQuantizationDetailsVector(flatbuffers::Verifier &verifier,
+ const flatbuffers::Vector<flatbuffers::Offset<void>> *values,
+ const flatbuffers::Vector<uint8_t> *types);
+
+enum DimensionType : int8_t
+{
+ DimensionType_DENSE = 0,
+ DimensionType_SPARSE_CSR = 1,
+ DimensionType_MIN = DimensionType_DENSE,
+ DimensionType_MAX = DimensionType_SPARSE_CSR
+};
+
+inline const DimensionType (&EnumValuesDimensionType())[2]
+{
+ static const DimensionType values[] = {DimensionType_DENSE, DimensionType_SPARSE_CSR};
+ return values;
+}
+
+inline const char *const *EnumNamesDimensionType()
+{
+ static const char *const names[3] = {"DENSE", "SPARSE_CSR", nullptr};
+ return names;
+}
+
+inline const char *EnumNameDimensionType(DimensionType e)
+{
+ if (flatbuffers::IsOutRange(e, DimensionType_DENSE, DimensionType_SPARSE_CSR))
+ return "";
+ const size_t index = static_cast<size_t>(e);
+ return EnumNamesDimensionType()[index];
+}
+
+enum SparseIndexVector : uint8_t
+{
+ SparseIndexVector_NONE = 0,
+ SparseIndexVector_Int32Vector = 1,
+ SparseIndexVector_Uint16Vector = 2,
+ SparseIndexVector_Uint8Vector = 3,
+ SparseIndexVector_MIN = SparseIndexVector_NONE,
+ SparseIndexVector_MAX = SparseIndexVector_Uint8Vector
+};
+
+inline const SparseIndexVector (&EnumValuesSparseIndexVector())[4]
+{
+ static const SparseIndexVector values[] = {SparseIndexVector_NONE, SparseIndexVector_Int32Vector,
+ SparseIndexVector_Uint16Vector,
+ SparseIndexVector_Uint8Vector};
+ return values;
+}
+
+inline const char *const *EnumNamesSparseIndexVector()
+{
+ static const char *const names[5] = {"NONE", "Int32Vector", "Uint16Vector", "Uint8Vector",
+ nullptr};
+ return names;
+}
+
+inline const char *EnumNameSparseIndexVector(SparseIndexVector e)
+{
+ if (flatbuffers::IsOutRange(e, SparseIndexVector_NONE, SparseIndexVector_Uint8Vector))
+ return "";
+ const size_t index = static_cast<size_t>(e);
+ return EnumNamesSparseIndexVector()[index];
+}
+
+template <typename T> struct SparseIndexVectorTraits
+{
+ static const SparseIndexVector enum_value = SparseIndexVector_NONE;
+};
+
+template <> struct SparseIndexVectorTraits<circle::Int32Vector>
+{
+ static const SparseIndexVector enum_value = SparseIndexVector_Int32Vector;
+};
+
+template <> struct SparseIndexVectorTraits<circle::Uint16Vector>
+{
+ static const SparseIndexVector enum_value = SparseIndexVector_Uint16Vector;
+};
+
+template <> struct SparseIndexVectorTraits<circle::Uint8Vector>
+{
+ static const SparseIndexVector enum_value = SparseIndexVector_Uint8Vector;
+};
+
+struct SparseIndexVectorUnion
+{
+ SparseIndexVector type;
+ void *value;
+
+ SparseIndexVectorUnion() : type(SparseIndexVector_NONE), value(nullptr) {}
+ SparseIndexVectorUnion(SparseIndexVectorUnion &&u) FLATBUFFERS_NOEXCEPT
+ : type(SparseIndexVector_NONE),
+ value(nullptr)
+ {
+ std::swap(type, u.type);
+ std::swap(value, u.value);
+ }
+ SparseIndexVectorUnion(const SparseIndexVectorUnion &);
+ SparseIndexVectorUnion &operator=(const SparseIndexVectorUnion &u)
+ {
+ SparseIndexVectorUnion t(u);
+ std::swap(type, t.type);
+ std::swap(value, t.value);
+ return *this;
+ }
+ SparseIndexVectorUnion &operator=(SparseIndexVectorUnion &&u) FLATBUFFERS_NOEXCEPT
+ {
+ std::swap(type, u.type);
+ std::swap(value, u.value);
+ return *this;
+ }
+ ~SparseIndexVectorUnion() { Reset(); }
+
+ void Reset();
+
+#ifndef FLATBUFFERS_CPP98_STL
+ template <typename T> void Set(T &&val)
+ {
+ using RT = typename std::remove_reference<T>::type;
+ Reset();
+ type = SparseIndexVectorTraits<typename RT::TableType>::enum_value;
+ if (type != SparseIndexVector_NONE)
+ {
+ value = new RT(std::forward<T>(val));
+ }
+ }
+#endif // FLATBUFFERS_CPP98_STL
+
+ static void *UnPack(const void *obj, SparseIndexVector type,
+ const flatbuffers::resolver_function_t *resolver);
+ flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr) const;
+
+ circle::Int32VectorT *AsInt32Vector()
+ {
+ return type == SparseIndexVector_Int32Vector ? reinterpret_cast<circle::Int32VectorT *>(value)
+ : nullptr;
+ }
+ const circle::Int32VectorT *AsInt32Vector() const
+ {
+ return type == SparseIndexVector_Int32Vector
+ ? reinterpret_cast<const circle::Int32VectorT *>(value)
+ : nullptr;
+ }
+ circle::Uint16VectorT *AsUint16Vector()
+ {
+ return type == SparseIndexVector_Uint16Vector ? reinterpret_cast<circle::Uint16VectorT *>(value)
+ : nullptr;
+ }
+ const circle::Uint16VectorT *AsUint16Vector() const
+ {
+ return type == SparseIndexVector_Uint16Vector
+ ? reinterpret_cast<const circle::Uint16VectorT *>(value)
+ : nullptr;
+ }
+ circle::Uint8VectorT *AsUint8Vector()
+ {
+ return type == SparseIndexVector_Uint8Vector ? reinterpret_cast<circle::Uint8VectorT *>(value)
+ : nullptr;
+ }
+ const circle::Uint8VectorT *AsUint8Vector() const
+ {
+ return type == SparseIndexVector_Uint8Vector
+ ? reinterpret_cast<const circle::Uint8VectorT *>(value)
+ : nullptr;
+ }
+};
+
+bool VerifySparseIndexVector(flatbuffers::Verifier &verifier, const void *obj,
+ SparseIndexVector type);
+bool VerifySparseIndexVectorVector(flatbuffers::Verifier &verifier,
+ const flatbuffers::Vector<flatbuffers::Offset<void>> *values,
+ const flatbuffers::Vector<uint8_t> *types);
+
+enum BuiltinOperator : int32_t
+{
+ BuiltinOperator_BCQ_GATHER = -4,
+ BuiltinOperator_BCQ_FULLY_CONNECTED = -3,
+ BuiltinOperator_INSTANCE_NORM = -2,
+ BuiltinOperator_ADD = 0,
+ BuiltinOperator_AVERAGE_POOL_2D = 1,
+ BuiltinOperator_CONCATENATION = 2,
+ BuiltinOperator_CONV_2D = 3,
+ BuiltinOperator_DEPTHWISE_CONV_2D = 4,
+ BuiltinOperator_DEPTH_TO_SPACE = 5,
+ BuiltinOperator_DEQUANTIZE = 6,
+ BuiltinOperator_EMBEDDING_LOOKUP = 7,
+ BuiltinOperator_FLOOR = 8,
+ BuiltinOperator_FULLY_CONNECTED = 9,
+ BuiltinOperator_HASHTABLE_LOOKUP = 10,
+ BuiltinOperator_L2_NORMALIZATION = 11,
+ BuiltinOperator_L2_POOL_2D = 12,
+ BuiltinOperator_LOCAL_RESPONSE_NORMALIZATION = 13,
+ BuiltinOperator_LOGISTIC = 14,
+ BuiltinOperator_LSH_PROJECTION = 15,
+ BuiltinOperator_LSTM = 16,
+ BuiltinOperator_MAX_POOL_2D = 17,
+ BuiltinOperator_MUL = 18,
+ BuiltinOperator_RELU = 19,
+ BuiltinOperator_RELU_N1_TO_1 = 20,
+ BuiltinOperator_RELU6 = 21,
+ BuiltinOperator_RESHAPE = 22,
+ BuiltinOperator_RESIZE_BILINEAR = 23,
+ BuiltinOperator_RNN = 24,
+ BuiltinOperator_SOFTMAX = 25,
+ BuiltinOperator_SPACE_TO_DEPTH = 26,
+ BuiltinOperator_SVDF = 27,
+ BuiltinOperator_TANH = 28,
+ BuiltinOperator_CONCAT_EMBEDDINGS = 29,
+ BuiltinOperator_SKIP_GRAM = 30,
+ BuiltinOperator_CALL = 31,
+ BuiltinOperator_CUSTOM = 32,
+ BuiltinOperator_EMBEDDING_LOOKUP_SPARSE = 33,
+ BuiltinOperator_PAD = 34,
+ BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_RNN = 35,
+ BuiltinOperator_GATHER = 36,
+ BuiltinOperator_BATCH_TO_SPACE_ND = 37,
+ BuiltinOperator_SPACE_TO_BATCH_ND = 38,
+ BuiltinOperator_TRANSPOSE = 39,
+ BuiltinOperator_MEAN = 40,
+ BuiltinOperator_SUB = 41,
+ BuiltinOperator_DIV = 42,
+ BuiltinOperator_SQUEEZE = 43,
+ BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_LSTM = 44,
+ BuiltinOperator_STRIDED_SLICE = 45,
+ BuiltinOperator_BIDIRECTIONAL_SEQUENCE_RNN = 46,
+ BuiltinOperator_EXP = 47,
+ BuiltinOperator_TOPK_V2 = 48,
+ BuiltinOperator_SPLIT = 49,
+ BuiltinOperator_LOG_SOFTMAX = 50,
+ BuiltinOperator_DELEGATE = 51,
+ BuiltinOperator_BIDIRECTIONAL_SEQUENCE_LSTM = 52,
+ BuiltinOperator_CAST = 53,
+ BuiltinOperator_PRELU = 54,
+ BuiltinOperator_MAXIMUM = 55,
+ BuiltinOperator_ARG_MAX = 56,
+ BuiltinOperator_MINIMUM = 57,
+ BuiltinOperator_LESS = 58,
+ BuiltinOperator_NEG = 59,
+ BuiltinOperator_PADV2 = 60,
+ BuiltinOperator_GREATER = 61,
+ BuiltinOperator_GREATER_EQUAL = 62,
+ BuiltinOperator_LESS_EQUAL = 63,
+ BuiltinOperator_SELECT = 64,
+ BuiltinOperator_SLICE = 65,
+ BuiltinOperator_SIN = 66,
+ BuiltinOperator_TRANSPOSE_CONV = 67,
+ BuiltinOperator_SPARSE_TO_DENSE = 68,
+ BuiltinOperator_TILE = 69,
+ BuiltinOperator_EXPAND_DIMS = 70,
+ BuiltinOperator_EQUAL = 71,
+ BuiltinOperator_NOT_EQUAL = 72,
+ BuiltinOperator_LOG = 73,
+ BuiltinOperator_SUM = 74,
+ BuiltinOperator_SQRT = 75,
+ BuiltinOperator_RSQRT = 76,
+ BuiltinOperator_SHAPE = 77,
+ BuiltinOperator_POW = 78,
+ BuiltinOperator_ARG_MIN = 79,
+ BuiltinOperator_FAKE_QUANT = 80,
+ BuiltinOperator_REDUCE_PROD = 81,
+ BuiltinOperator_REDUCE_MAX = 82,
+ BuiltinOperator_PACK = 83,
+ BuiltinOperator_LOGICAL_OR = 84,
+ BuiltinOperator_ONE_HOT = 85,
+ BuiltinOperator_LOGICAL_AND = 86,
+ BuiltinOperator_LOGICAL_NOT = 87,
+ BuiltinOperator_UNPACK = 88,
+ BuiltinOperator_REDUCE_MIN = 89,
+ BuiltinOperator_FLOOR_DIV = 90,
+ BuiltinOperator_REDUCE_ANY = 91,
+ BuiltinOperator_SQUARE = 92,
+ BuiltinOperator_ZEROS_LIKE = 93,
+ BuiltinOperator_FILL = 94,
+ BuiltinOperator_FLOOR_MOD = 95,
+ BuiltinOperator_RANGE = 96,
+ BuiltinOperator_RESIZE_NEAREST_NEIGHBOR = 97,
+ BuiltinOperator_LEAKY_RELU = 98,
+ BuiltinOperator_SQUARED_DIFFERENCE = 99,
+ BuiltinOperator_MIRROR_PAD = 100,
+ BuiltinOperator_ABS = 101,
+ BuiltinOperator_SPLIT_V = 102,
+ BuiltinOperator_UNIQUE = 103,
+ BuiltinOperator_CEIL = 104,
+ BuiltinOperator_REVERSE_V2 = 105,
+ BuiltinOperator_ADD_N = 106,
+ BuiltinOperator_GATHER_ND = 107,
+ BuiltinOperator_COS = 108,
+ BuiltinOperator_WHERE = 109,
+ BuiltinOperator_RANK = 110,
+ BuiltinOperator_ELU = 111,
+ BuiltinOperator_REVERSE_SEQUENCE = 112,
+ BuiltinOperator_MATRIX_DIAG = 113,
+ BuiltinOperator_QUANTIZE = 114,
+ BuiltinOperator_MATRIX_SET_DIAG = 115,
+ BuiltinOperator_ROUND = 116,
+ BuiltinOperator_HARD_SWISH = 117,
+ BuiltinOperator_IF = 118,
+ BuiltinOperator_WHILE = 119,
+ BuiltinOperator_NON_MAX_SUPPRESSION_V4 = 120,
+ BuiltinOperator_NON_MAX_SUPPRESSION_V5 = 121,
+ BuiltinOperator_SCATTER_ND = 122,
+ BuiltinOperator_SELECT_V2 = 123,
+ BuiltinOperator_DENSIFY = 124,
+ BuiltinOperator_SEGMENT_SUM = 125,
+ BuiltinOperator_BATCH_MATMUL = 126,
+ BuiltinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES = 127,
+ BuiltinOperator_CUMSUM = 128,
+ BuiltinOperator_CALL_ONCE = 129,
+ BuiltinOperator_BROADCAST_TO = 130,
+ BuiltinOperator_RFFT2D = 131,
+ BuiltinOperator_CONV_3D = 132,
+ BuiltinOperator_IMAG = 133,
+ BuiltinOperator_REAL = 134,
+ BuiltinOperator_COMPLEX_ABS = 135,
+ BuiltinOperator_HASHTABLE = 136,
+ BuiltinOperator_HASHTABLE_FIND = 137,
+ BuiltinOperator_HASHTABLE_IMPORT = 138,
+ BuiltinOperator_HASHTABLE_SIZE = 139,
+ BuiltinOperator_REDUCE_ALL = 140,
+ BuiltinOperator_CONV_3D_TRANSPOSE = 141,
+ BuiltinOperator_VAR_HANDLE = 142,
+ BuiltinOperator_READ_VARIABLE = 143,
+ BuiltinOperator_ASSIGN_VARIABLE = 144,
+ BuiltinOperator_BROADCAST_ARGS = 145,
+ BuiltinOperator_RANDOM_STANDARD_NORMAL = 146,
+ BuiltinOperator_MIN = BuiltinOperator_BCQ_GATHER,
+ BuiltinOperator_MAX = BuiltinOperator_RANDOM_STANDARD_NORMAL
+};
+
+inline const BuiltinOperator (&EnumValuesBuiltinOperator())[150]
+{
+ static const BuiltinOperator values[] = {BuiltinOperator_BCQ_GATHER,
+ BuiltinOperator_BCQ_FULLY_CONNECTED,
+ BuiltinOperator_INSTANCE_NORM,
+ BuiltinOperator_ADD,
+ BuiltinOperator_AVERAGE_POOL_2D,
+ BuiltinOperator_CONCATENATION,
+ BuiltinOperator_CONV_2D,
+ BuiltinOperator_DEPTHWISE_CONV_2D,
+ BuiltinOperator_DEPTH_TO_SPACE,
+ BuiltinOperator_DEQUANTIZE,
+ BuiltinOperator_EMBEDDING_LOOKUP,
+ BuiltinOperator_FLOOR,
+ BuiltinOperator_FULLY_CONNECTED,
+ BuiltinOperator_HASHTABLE_LOOKUP,
+ BuiltinOperator_L2_NORMALIZATION,
+ BuiltinOperator_L2_POOL_2D,
+ BuiltinOperator_LOCAL_RESPONSE_NORMALIZATION,
+ BuiltinOperator_LOGISTIC,
+ BuiltinOperator_LSH_PROJECTION,
+ BuiltinOperator_LSTM,
+ BuiltinOperator_MAX_POOL_2D,
+ BuiltinOperator_MUL,
+ BuiltinOperator_RELU,
+ BuiltinOperator_RELU_N1_TO_1,
+ BuiltinOperator_RELU6,
+ BuiltinOperator_RESHAPE,
+ BuiltinOperator_RESIZE_BILINEAR,
+ BuiltinOperator_RNN,
+ BuiltinOperator_SOFTMAX,
+ BuiltinOperator_SPACE_TO_DEPTH,
+ BuiltinOperator_SVDF,
+ BuiltinOperator_TANH,
+ BuiltinOperator_CONCAT_EMBEDDINGS,
+ BuiltinOperator_SKIP_GRAM,
+ BuiltinOperator_CALL,
+ BuiltinOperator_CUSTOM,
+ BuiltinOperator_EMBEDDING_LOOKUP_SPARSE,
+ BuiltinOperator_PAD,
+ BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_RNN,
+ BuiltinOperator_GATHER,
+ BuiltinOperator_BATCH_TO_SPACE_ND,
+ BuiltinOperator_SPACE_TO_BATCH_ND,
+ BuiltinOperator_TRANSPOSE,
+ BuiltinOperator_MEAN,
+ BuiltinOperator_SUB,
+ BuiltinOperator_DIV,
+ BuiltinOperator_SQUEEZE,
+ BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_LSTM,
+ BuiltinOperator_STRIDED_SLICE,
+ BuiltinOperator_BIDIRECTIONAL_SEQUENCE_RNN,
+ BuiltinOperator_EXP,
+ BuiltinOperator_TOPK_V2,
+ BuiltinOperator_SPLIT,
+ BuiltinOperator_LOG_SOFTMAX,
+ BuiltinOperator_DELEGATE,
+ BuiltinOperator_BIDIRECTIONAL_SEQUENCE_LSTM,
+ BuiltinOperator_CAST,
+ BuiltinOperator_PRELU,
+ BuiltinOperator_MAXIMUM,
+ BuiltinOperator_ARG_MAX,
+ BuiltinOperator_MINIMUM,
+ BuiltinOperator_LESS,
+ BuiltinOperator_NEG,
+ BuiltinOperator_PADV2,
+ BuiltinOperator_GREATER,
+ BuiltinOperator_GREATER_EQUAL,
+ BuiltinOperator_LESS_EQUAL,
+ BuiltinOperator_SELECT,
+ BuiltinOperator_SLICE,
+ BuiltinOperator_SIN,
+ BuiltinOperator_TRANSPOSE_CONV,
+ BuiltinOperator_SPARSE_TO_DENSE,
+ BuiltinOperator_TILE,
+ BuiltinOperator_EXPAND_DIMS,
+ BuiltinOperator_EQUAL,
+ BuiltinOperator_NOT_EQUAL,
+ BuiltinOperator_LOG,
+ BuiltinOperator_SUM,
+ BuiltinOperator_SQRT,
+ BuiltinOperator_RSQRT,
+ BuiltinOperator_SHAPE,
+ BuiltinOperator_POW,
+ BuiltinOperator_ARG_MIN,
+ BuiltinOperator_FAKE_QUANT,
+ BuiltinOperator_REDUCE_PROD,
+ BuiltinOperator_REDUCE_MAX,
+ BuiltinOperator_PACK,
+ BuiltinOperator_LOGICAL_OR,
+ BuiltinOperator_ONE_HOT,
+ BuiltinOperator_LOGICAL_AND,
+ BuiltinOperator_LOGICAL_NOT,
+ BuiltinOperator_UNPACK,
+ BuiltinOperator_REDUCE_MIN,
+ BuiltinOperator_FLOOR_DIV,
+ BuiltinOperator_REDUCE_ANY,
+ BuiltinOperator_SQUARE,
+ BuiltinOperator_ZEROS_LIKE,
+ BuiltinOperator_FILL,
+ BuiltinOperator_FLOOR_MOD,
+ BuiltinOperator_RANGE,
+ BuiltinOperator_RESIZE_NEAREST_NEIGHBOR,
+ BuiltinOperator_LEAKY_RELU,
+ BuiltinOperator_SQUARED_DIFFERENCE,
+ BuiltinOperator_MIRROR_PAD,
+ BuiltinOperator_ABS,
+ BuiltinOperator_SPLIT_V,
+ BuiltinOperator_UNIQUE,
+ BuiltinOperator_CEIL,
+ BuiltinOperator_REVERSE_V2,
+ BuiltinOperator_ADD_N,
+ BuiltinOperator_GATHER_ND,
+ BuiltinOperator_COS,
+ BuiltinOperator_WHERE,
+ BuiltinOperator_RANK,
+ BuiltinOperator_ELU,
+ BuiltinOperator_REVERSE_SEQUENCE,
+ BuiltinOperator_MATRIX_DIAG,
+ BuiltinOperator_QUANTIZE,
+ BuiltinOperator_MATRIX_SET_DIAG,
+ BuiltinOperator_ROUND,
+ BuiltinOperator_HARD_SWISH,
+ BuiltinOperator_IF,
+ BuiltinOperator_WHILE,
+ BuiltinOperator_NON_MAX_SUPPRESSION_V4,
+ BuiltinOperator_NON_MAX_SUPPRESSION_V5,
+ BuiltinOperator_SCATTER_ND,
+ BuiltinOperator_SELECT_V2,
+ BuiltinOperator_DENSIFY,
+ BuiltinOperator_SEGMENT_SUM,
+ BuiltinOperator_BATCH_MATMUL,
+ BuiltinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES,
+ BuiltinOperator_CUMSUM,
+ BuiltinOperator_CALL_ONCE,
+ BuiltinOperator_BROADCAST_TO,
+ BuiltinOperator_RFFT2D,
+ BuiltinOperator_CONV_3D,
+ BuiltinOperator_IMAG,
+ BuiltinOperator_REAL,
+ BuiltinOperator_COMPLEX_ABS,
+ BuiltinOperator_HASHTABLE,
+ BuiltinOperator_HASHTABLE_FIND,
+ BuiltinOperator_HASHTABLE_IMPORT,
+ BuiltinOperator_HASHTABLE_SIZE,
+ BuiltinOperator_REDUCE_ALL,
+ BuiltinOperator_CONV_3D_TRANSPOSE,
+ BuiltinOperator_VAR_HANDLE,
+ BuiltinOperator_READ_VARIABLE,
+ BuiltinOperator_ASSIGN_VARIABLE,
+ BuiltinOperator_BROADCAST_ARGS,
+ BuiltinOperator_RANDOM_STANDARD_NORMAL};
+ return values;
+}
+
+inline const char *const *EnumNamesBuiltinOperator()
+{
+ static const char *const names[152] = {"BCQ_GATHER",
+ "BCQ_FULLY_CONNECTED",
+ "INSTANCE_NORM",
+ "",
+ "ADD",
+ "AVERAGE_POOL_2D",
+ "CONCATENATION",
+ "CONV_2D",
+ "DEPTHWISE_CONV_2D",
+ "DEPTH_TO_SPACE",
+ "DEQUANTIZE",
+ "EMBEDDING_LOOKUP",
+ "FLOOR",
+ "FULLY_CONNECTED",
+ "HASHTABLE_LOOKUP",
+ "L2_NORMALIZATION",
+ "L2_POOL_2D",
+ "LOCAL_RESPONSE_NORMALIZATION",
+ "LOGISTIC",
+ "LSH_PROJECTION",
+ "LSTM",
+ "MAX_POOL_2D",
+ "MUL",
+ "RELU",
+ "RELU_N1_TO_1",
+ "RELU6",
+ "RESHAPE",
+ "RESIZE_BILINEAR",
+ "RNN",
+ "SOFTMAX",
+ "SPACE_TO_DEPTH",
+ "SVDF",
+ "TANH",
+ "CONCAT_EMBEDDINGS",
+ "SKIP_GRAM",
+ "CALL",
+ "CUSTOM",
+ "EMBEDDING_LOOKUP_SPARSE",
+ "PAD",
+ "UNIDIRECTIONAL_SEQUENCE_RNN",
+ "GATHER",
+ "BATCH_TO_SPACE_ND",
+ "SPACE_TO_BATCH_ND",
+ "TRANSPOSE",
+ "MEAN",
+ "SUB",
+ "DIV",
+ "SQUEEZE",
+ "UNIDIRECTIONAL_SEQUENCE_LSTM",
+ "STRIDED_SLICE",
+ "BIDIRECTIONAL_SEQUENCE_RNN",
+ "EXP",
+ "TOPK_V2",
+ "SPLIT",
+ "LOG_SOFTMAX",
+ "DELEGATE",
+ "BIDIRECTIONAL_SEQUENCE_LSTM",
+ "CAST",
+ "PRELU",
+ "MAXIMUM",
+ "ARG_MAX",
+ "MINIMUM",
+ "LESS",
+ "NEG",
+ "PADV2",
+ "GREATER",
+ "GREATER_EQUAL",
+ "LESS_EQUAL",
+ "SELECT",
+ "SLICE",
+ "SIN",
+ "TRANSPOSE_CONV",
+ "SPARSE_TO_DENSE",
+ "TILE",
+ "EXPAND_DIMS",
+ "EQUAL",
+ "NOT_EQUAL",
+ "LOG",
+ "SUM",
+ "SQRT",
+ "RSQRT",
+ "SHAPE",
+ "POW",
+ "ARG_MIN",
+ "FAKE_QUANT",
+ "REDUCE_PROD",
+ "REDUCE_MAX",
+ "PACK",
+ "LOGICAL_OR",
+ "ONE_HOT",
+ "LOGICAL_AND",
+ "LOGICAL_NOT",
+ "UNPACK",
+ "REDUCE_MIN",
+ "FLOOR_DIV",
+ "REDUCE_ANY",
+ "SQUARE",
+ "ZEROS_LIKE",
+ "FILL",
+ "FLOOR_MOD",
+ "RANGE",
+ "RESIZE_NEAREST_NEIGHBOR",
+ "LEAKY_RELU",
+ "SQUARED_DIFFERENCE",
+ "MIRROR_PAD",
+ "ABS",
+ "SPLIT_V",
+ "UNIQUE",
+ "CEIL",
+ "REVERSE_V2",
+ "ADD_N",
+ "GATHER_ND",
+ "COS",
+ "WHERE",
+ "RANK",
+ "ELU",
+ "REVERSE_SEQUENCE",
+ "MATRIX_DIAG",
+ "QUANTIZE",
+ "MATRIX_SET_DIAG",
+ "ROUND",
+ "HARD_SWISH",
+ "IF",
+ "WHILE",
+ "NON_MAX_SUPPRESSION_V4",
+ "NON_MAX_SUPPRESSION_V5",
+ "SCATTER_ND",
+ "SELECT_V2",
+ "DENSIFY",
+ "SEGMENT_SUM",
+ "BATCH_MATMUL",
+ "PLACEHOLDER_FOR_GREATER_OP_CODES",
+ "CUMSUM",
+ "CALL_ONCE",
+ "BROADCAST_TO",
+ "RFFT2D",
+ "CONV_3D",
+ "IMAG",
+ "REAL",
+ "COMPLEX_ABS",
+ "HASHTABLE",
+ "HASHTABLE_FIND",
+ "HASHTABLE_IMPORT",
+ "HASHTABLE_SIZE",
+ "REDUCE_ALL",
+ "CONV_3D_TRANSPOSE",
+ "VAR_HANDLE",
+ "READ_VARIABLE",
+ "ASSIGN_VARIABLE",
+ "BROADCAST_ARGS",
+ "RANDOM_STANDARD_NORMAL",
+ nullptr};
+ return names;
+}
+
+inline const char *EnumNameBuiltinOperator(BuiltinOperator e)
+{
+ if (flatbuffers::IsOutRange(e, BuiltinOperator_BCQ_GATHER,
+ BuiltinOperator_RANDOM_STANDARD_NORMAL))
+ return "";
+ const size_t index = static_cast<size_t>(e) - static_cast<size_t>(BuiltinOperator_BCQ_GATHER);
+ return EnumNamesBuiltinOperator()[index];
+}
+
+enum BuiltinOptions : uint8_t
+{
+ BuiltinOptions_NONE = 0,
+ BuiltinOptions_Conv2DOptions = 1,
+ BuiltinOptions_DepthwiseConv2DOptions = 2,
+ BuiltinOptions_ConcatEmbeddingsOptions = 3,
+ BuiltinOptions_LSHProjectionOptions = 4,
+ BuiltinOptions_Pool2DOptions = 5,
+ BuiltinOptions_SVDFOptions = 6,
+ BuiltinOptions_RNNOptions = 7,
+ BuiltinOptions_FullyConnectedOptions = 8,
+ BuiltinOptions_SoftmaxOptions = 9,
+ BuiltinOptions_ConcatenationOptions = 10,
+ BuiltinOptions_AddOptions = 11,
+ BuiltinOptions_L2NormOptions = 12,
+ BuiltinOptions_LocalResponseNormalizationOptions = 13,
+ BuiltinOptions_LSTMOptions = 14,
+ BuiltinOptions_ResizeBilinearOptions = 15,
+ BuiltinOptions_CallOptions = 16,
+ BuiltinOptions_ReshapeOptions = 17,
+ BuiltinOptions_SkipGramOptions = 18,
+ BuiltinOptions_SpaceToDepthOptions = 19,
+ BuiltinOptions_EmbeddingLookupSparseOptions = 20,
+ BuiltinOptions_MulOptions = 21,
+ BuiltinOptions_PadOptions = 22,
+ BuiltinOptions_GatherOptions = 23,
+ BuiltinOptions_BatchToSpaceNDOptions = 24,
+ BuiltinOptions_SpaceToBatchNDOptions = 25,
+ BuiltinOptions_TransposeOptions = 26,
+ BuiltinOptions_ReducerOptions = 27,
+ BuiltinOptions_SubOptions = 28,
+ BuiltinOptions_DivOptions = 29,
+ BuiltinOptions_SqueezeOptions = 30,
+ BuiltinOptions_SequenceRNNOptions = 31,
+ BuiltinOptions_StridedSliceOptions = 32,
+ BuiltinOptions_ExpOptions = 33,
+ BuiltinOptions_TopKV2Options = 34,
+ BuiltinOptions_SplitOptions = 35,
+ BuiltinOptions_LogSoftmaxOptions = 36,
+ BuiltinOptions_CastOptions = 37,
+ BuiltinOptions_DequantizeOptions = 38,
+ BuiltinOptions_MaximumMinimumOptions = 39,
+ BuiltinOptions_ArgMaxOptions = 40,
+ BuiltinOptions_LessOptions = 41,
+ BuiltinOptions_NegOptions = 42,
+ BuiltinOptions_PadV2Options = 43,
+ BuiltinOptions_GreaterOptions = 44,
+ BuiltinOptions_GreaterEqualOptions = 45,
+ BuiltinOptions_LessEqualOptions = 46,
+ BuiltinOptions_SelectOptions = 47,
+ BuiltinOptions_SliceOptions = 48,
+ BuiltinOptions_TransposeConvOptions = 49,
+ BuiltinOptions_SparseToDenseOptions = 50,
+ BuiltinOptions_TileOptions = 51,
+ BuiltinOptions_ExpandDimsOptions = 52,
+ BuiltinOptions_EqualOptions = 53,
+ BuiltinOptions_NotEqualOptions = 54,
+ BuiltinOptions_ShapeOptions = 55,
+ BuiltinOptions_PowOptions = 56,
+ BuiltinOptions_ArgMinOptions = 57,
+ BuiltinOptions_FakeQuantOptions = 58,
+ BuiltinOptions_PackOptions = 59,
+ BuiltinOptions_LogicalOrOptions = 60,
+ BuiltinOptions_OneHotOptions = 61,
+ BuiltinOptions_LogicalAndOptions = 62,
+ BuiltinOptions_LogicalNotOptions = 63,
+ BuiltinOptions_UnpackOptions = 64,
+ BuiltinOptions_FloorDivOptions = 65,
+ BuiltinOptions_SquareOptions = 66,
+ BuiltinOptions_ZerosLikeOptions = 67,
+ BuiltinOptions_FillOptions = 68,
+ BuiltinOptions_BidirectionalSequenceLSTMOptions = 69,
+ BuiltinOptions_BidirectionalSequenceRNNOptions = 70,
+ BuiltinOptions_UnidirectionalSequenceLSTMOptions = 71,
+ BuiltinOptions_FloorModOptions = 72,
+ BuiltinOptions_RangeOptions = 73,
+ BuiltinOptions_ResizeNearestNeighborOptions = 74,
+ BuiltinOptions_LeakyReluOptions = 75,
+ BuiltinOptions_SquaredDifferenceOptions = 76,
+ BuiltinOptions_MirrorPadOptions = 77,
+ BuiltinOptions_AbsOptions = 78,
+ BuiltinOptions_SplitVOptions = 79,
+ BuiltinOptions_UniqueOptions = 80,
+ BuiltinOptions_ReverseV2Options = 81,
+ BuiltinOptions_AddNOptions = 82,
+ BuiltinOptions_GatherNdOptions = 83,
+ BuiltinOptions_CosOptions = 84,
+ BuiltinOptions_WhereOptions = 85,
+ BuiltinOptions_RankOptions = 86,
+ BuiltinOptions_ReverseSequenceOptions = 87,
+ BuiltinOptions_MatrixDiagOptions = 88,
+ BuiltinOptions_QuantizeOptions = 89,
+ BuiltinOptions_MatrixSetDiagOptions = 90,
+ BuiltinOptions_HardSwishOptions = 91,
+ BuiltinOptions_IfOptions = 92,
+ BuiltinOptions_WhileOptions = 93,
+ BuiltinOptions_DepthToSpaceOptions = 94,
+ BuiltinOptions_NonMaxSuppressionV4Options = 95,
+ BuiltinOptions_NonMaxSuppressionV5Options = 96,
+ BuiltinOptions_ScatterNdOptions = 97,
+ BuiltinOptions_SelectV2Options = 98,
+ BuiltinOptions_DensifyOptions = 99,
+ BuiltinOptions_SegmentSumOptions = 100,
+ BuiltinOptions_BatchMatMulOptions = 101,
+ BuiltinOptions_CumsumOptions = 102,
+ BuiltinOptions_CallOnceOptions = 103,
+ BuiltinOptions_BroadcastToOptions = 104,
+ BuiltinOptions_Rfft2dOptions = 105,
+ BuiltinOptions_Conv3DOptions = 106,
+ BuiltinOptions_HashtableOptions = 107,
+ BuiltinOptions_HashtableFindOptions = 108,
+ BuiltinOptions_HashtableImportOptions = 109,
+ BuiltinOptions_HashtableSizeOptions = 110,
+ BuiltinOptions_VarHandleOptions = 111,
+ BuiltinOptions_ReadVariableOptions = 112,
+ BuiltinOptions_AssignVariableOptions = 113,
+ BuiltinOptions_RandomOptions = 114,
+ BuiltinOptions_BCQGatherOptions = 252,
+ BuiltinOptions_BCQFullyConnectedOptions = 253,
+ BuiltinOptions_InstanceNormOptions = 254,
+ BuiltinOptions_MIN = BuiltinOptions_NONE,
+ BuiltinOptions_MAX = BuiltinOptions_InstanceNormOptions
+};
+
+inline const BuiltinOptions (&EnumValuesBuiltinOptions())[118]
+{
+ static const BuiltinOptions values[] = {BuiltinOptions_NONE,
+ BuiltinOptions_Conv2DOptions,
+ BuiltinOptions_DepthwiseConv2DOptions,
+ BuiltinOptions_ConcatEmbeddingsOptions,
+ BuiltinOptions_LSHProjectionOptions,
+ BuiltinOptions_Pool2DOptions,
+ BuiltinOptions_SVDFOptions,
+ BuiltinOptions_RNNOptions,
+ BuiltinOptions_FullyConnectedOptions,
+ BuiltinOptions_SoftmaxOptions,
+ BuiltinOptions_ConcatenationOptions,
+ BuiltinOptions_AddOptions,
+ BuiltinOptions_L2NormOptions,
+ BuiltinOptions_LocalResponseNormalizationOptions,
+ BuiltinOptions_LSTMOptions,
+ BuiltinOptions_ResizeBilinearOptions,
+ BuiltinOptions_CallOptions,
+ BuiltinOptions_ReshapeOptions,
+ BuiltinOptions_SkipGramOptions,
+ BuiltinOptions_SpaceToDepthOptions,
+ BuiltinOptions_EmbeddingLookupSparseOptions,
+ BuiltinOptions_MulOptions,
+ BuiltinOptions_PadOptions,
+ BuiltinOptions_GatherOptions,
+ BuiltinOptions_BatchToSpaceNDOptions,
+ BuiltinOptions_SpaceToBatchNDOptions,
+ BuiltinOptions_TransposeOptions,
+ BuiltinOptions_ReducerOptions,
+ BuiltinOptions_SubOptions,
+ BuiltinOptions_DivOptions,
+ BuiltinOptions_SqueezeOptions,
+ BuiltinOptions_SequenceRNNOptions,
+ BuiltinOptions_StridedSliceOptions,
+ BuiltinOptions_ExpOptions,
+ BuiltinOptions_TopKV2Options,
+ BuiltinOptions_SplitOptions,
+ BuiltinOptions_LogSoftmaxOptions,
+ BuiltinOptions_CastOptions,
+ BuiltinOptions_DequantizeOptions,
+ BuiltinOptions_MaximumMinimumOptions,
+ BuiltinOptions_ArgMaxOptions,
+ BuiltinOptions_LessOptions,
+ BuiltinOptions_NegOptions,
+ BuiltinOptions_PadV2Options,
+ BuiltinOptions_GreaterOptions,
+ BuiltinOptions_GreaterEqualOptions,
+ BuiltinOptions_LessEqualOptions,
+ BuiltinOptions_SelectOptions,
+ BuiltinOptions_SliceOptions,
+ BuiltinOptions_TransposeConvOptions,
+ BuiltinOptions_SparseToDenseOptions,
+ BuiltinOptions_TileOptions,
+ BuiltinOptions_ExpandDimsOptions,
+ BuiltinOptions_EqualOptions,
+ BuiltinOptions_NotEqualOptions,
+ BuiltinOptions_ShapeOptions,
+ BuiltinOptions_PowOptions,
+ BuiltinOptions_ArgMinOptions,
+ BuiltinOptions_FakeQuantOptions,
+ BuiltinOptions_PackOptions,
+ BuiltinOptions_LogicalOrOptions,
+ BuiltinOptions_OneHotOptions,
+ BuiltinOptions_LogicalAndOptions,
+ BuiltinOptions_LogicalNotOptions,
+ BuiltinOptions_UnpackOptions,
+ BuiltinOptions_FloorDivOptions,
+ BuiltinOptions_SquareOptions,
+ BuiltinOptions_ZerosLikeOptions,
+ BuiltinOptions_FillOptions,
+ BuiltinOptions_BidirectionalSequenceLSTMOptions,
+ BuiltinOptions_BidirectionalSequenceRNNOptions,
+ BuiltinOptions_UnidirectionalSequenceLSTMOptions,
+ BuiltinOptions_FloorModOptions,
+ BuiltinOptions_RangeOptions,
+ BuiltinOptions_ResizeNearestNeighborOptions,
+ BuiltinOptions_LeakyReluOptions,
+ BuiltinOptions_SquaredDifferenceOptions,
+ BuiltinOptions_MirrorPadOptions,
+ BuiltinOptions_AbsOptions,
+ BuiltinOptions_SplitVOptions,
+ BuiltinOptions_UniqueOptions,
+ BuiltinOptions_ReverseV2Options,
+ BuiltinOptions_AddNOptions,
+ BuiltinOptions_GatherNdOptions,
+ BuiltinOptions_CosOptions,
+ BuiltinOptions_WhereOptions,
+ BuiltinOptions_RankOptions,
+ BuiltinOptions_ReverseSequenceOptions,
+ BuiltinOptions_MatrixDiagOptions,
+ BuiltinOptions_QuantizeOptions,
+ BuiltinOptions_MatrixSetDiagOptions,
+ BuiltinOptions_HardSwishOptions,
+ BuiltinOptions_IfOptions,
+ BuiltinOptions_WhileOptions,
+ BuiltinOptions_DepthToSpaceOptions,
+ BuiltinOptions_NonMaxSuppressionV4Options,
+ BuiltinOptions_NonMaxSuppressionV5Options,
+ BuiltinOptions_ScatterNdOptions,
+ BuiltinOptions_SelectV2Options,
+ BuiltinOptions_DensifyOptions,
+ BuiltinOptions_SegmentSumOptions,
+ BuiltinOptions_BatchMatMulOptions,
+ BuiltinOptions_CumsumOptions,
+ BuiltinOptions_CallOnceOptions,
+ BuiltinOptions_BroadcastToOptions,
+ BuiltinOptions_Rfft2dOptions,
+ BuiltinOptions_Conv3DOptions,
+ BuiltinOptions_HashtableOptions,
+ BuiltinOptions_HashtableFindOptions,
+ BuiltinOptions_HashtableImportOptions,
+ BuiltinOptions_HashtableSizeOptions,
+ BuiltinOptions_VarHandleOptions,
+ BuiltinOptions_ReadVariableOptions,
+ BuiltinOptions_AssignVariableOptions,
+ BuiltinOptions_RandomOptions,
+ BuiltinOptions_BCQGatherOptions,
+ BuiltinOptions_BCQFullyConnectedOptions,
+ BuiltinOptions_InstanceNormOptions};
+ return values;
+}
+
+inline const char *const *EnumNamesBuiltinOptions()
+{
+ static const char *const names[256] = {"NONE",
+ "Conv2DOptions",
+ "DepthwiseConv2DOptions",
+ "ConcatEmbeddingsOptions",
+ "LSHProjectionOptions",
+ "Pool2DOptions",
+ "SVDFOptions",
+ "RNNOptions",
+ "FullyConnectedOptions",
+ "SoftmaxOptions",
+ "ConcatenationOptions",
+ "AddOptions",
+ "L2NormOptions",
+ "LocalResponseNormalizationOptions",
+ "LSTMOptions",
+ "ResizeBilinearOptions",
+ "CallOptions",
+ "ReshapeOptions",
+ "SkipGramOptions",
+ "SpaceToDepthOptions",
+ "EmbeddingLookupSparseOptions",
+ "MulOptions",
+ "PadOptions",
+ "GatherOptions",
+ "BatchToSpaceNDOptions",
+ "SpaceToBatchNDOptions",
+ "TransposeOptions",
+ "ReducerOptions",
+ "SubOptions",
+ "DivOptions",
+ "SqueezeOptions",
+ "SequenceRNNOptions",
+ "StridedSliceOptions",
+ "ExpOptions",
+ "TopKV2Options",
+ "SplitOptions",
+ "LogSoftmaxOptions",
+ "CastOptions",
+ "DequantizeOptions",
+ "MaximumMinimumOptions",
+ "ArgMaxOptions",
+ "LessOptions",
+ "NegOptions",
+ "PadV2Options",
+ "GreaterOptions",
+ "GreaterEqualOptions",
+ "LessEqualOptions",
+ "SelectOptions",
+ "SliceOptions",
+ "TransposeConvOptions",
+ "SparseToDenseOptions",
+ "TileOptions",
+ "ExpandDimsOptions",
+ "EqualOptions",
+ "NotEqualOptions",
+ "ShapeOptions",
+ "PowOptions",
+ "ArgMinOptions",
+ "FakeQuantOptions",
+ "PackOptions",
+ "LogicalOrOptions",
+ "OneHotOptions",
+ "LogicalAndOptions",
+ "LogicalNotOptions",
+ "UnpackOptions",
+ "FloorDivOptions",
+ "SquareOptions",
+ "ZerosLikeOptions",
+ "FillOptions",
+ "BidirectionalSequenceLSTMOptions",
+ "BidirectionalSequenceRNNOptions",
+ "UnidirectionalSequenceLSTMOptions",
+ "FloorModOptions",
+ "RangeOptions",
+ "ResizeNearestNeighborOptions",
+ "LeakyReluOptions",
+ "SquaredDifferenceOptions",
+ "MirrorPadOptions",
+ "AbsOptions",
+ "SplitVOptions",
+ "UniqueOptions",
+ "ReverseV2Options",
+ "AddNOptions",
+ "GatherNdOptions",
+ "CosOptions",
+ "WhereOptions",
+ "RankOptions",
+ "ReverseSequenceOptions",
+ "MatrixDiagOptions",
+ "QuantizeOptions",
+ "MatrixSetDiagOptions",
+ "HardSwishOptions",
+ "IfOptions",
+ "WhileOptions",
+ "DepthToSpaceOptions",
+ "NonMaxSuppressionV4Options",
+ "NonMaxSuppressionV5Options",
+ "ScatterNdOptions",
+ "SelectV2Options",
+ "DensifyOptions",
+ "SegmentSumOptions",
+ "BatchMatMulOptions",
+ "CumsumOptions",
+ "CallOnceOptions",
+ "BroadcastToOptions",
+ "Rfft2dOptions",
+ "Conv3DOptions",
+ "HashtableOptions",
+ "HashtableFindOptions",
+ "HashtableImportOptions",
+ "HashtableSizeOptions",
+ "VarHandleOptions",
+ "ReadVariableOptions",
+ "AssignVariableOptions",
+ "RandomOptions",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "BCQGatherOptions",
+ "BCQFullyConnectedOptions",
+ "InstanceNormOptions",
+ nullptr};
+ return names;
+}
+
+inline const char *EnumNameBuiltinOptions(BuiltinOptions e)
+{
+ if (flatbuffers::IsOutRange(e, BuiltinOptions_NONE, BuiltinOptions_InstanceNormOptions))
+ return "";
+ const size_t index = static_cast<size_t>(e);
+ return EnumNamesBuiltinOptions()[index];
+}
+
+template <typename T> struct BuiltinOptionsTraits
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_NONE;
+};
+
+template <> struct BuiltinOptionsTraits<circle::Conv2DOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_Conv2DOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::DepthwiseConv2DOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_DepthwiseConv2DOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::ConcatEmbeddingsOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_ConcatEmbeddingsOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::LSHProjectionOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_LSHProjectionOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::Pool2DOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_Pool2DOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::SVDFOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_SVDFOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::RNNOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_RNNOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::FullyConnectedOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_FullyConnectedOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::SoftmaxOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_SoftmaxOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::ConcatenationOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_ConcatenationOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::AddOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_AddOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::L2NormOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_L2NormOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::LocalResponseNormalizationOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_LocalResponseNormalizationOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::LSTMOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_LSTMOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::ResizeBilinearOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_ResizeBilinearOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::CallOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_CallOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::ReshapeOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_ReshapeOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::SkipGramOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_SkipGramOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::SpaceToDepthOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_SpaceToDepthOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::EmbeddingLookupSparseOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_EmbeddingLookupSparseOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::MulOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_MulOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::PadOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_PadOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::GatherOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_GatherOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::BatchToSpaceNDOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_BatchToSpaceNDOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::SpaceToBatchNDOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_SpaceToBatchNDOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::TransposeOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_TransposeOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::ReducerOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_ReducerOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::SubOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_SubOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::DivOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_DivOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::SqueezeOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_SqueezeOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::SequenceRNNOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_SequenceRNNOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::StridedSliceOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_StridedSliceOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::ExpOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_ExpOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::TopKV2Options>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_TopKV2Options;
+};
+
+template <> struct BuiltinOptionsTraits<circle::SplitOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_SplitOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::LogSoftmaxOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_LogSoftmaxOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::CastOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_CastOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::DequantizeOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_DequantizeOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::MaximumMinimumOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_MaximumMinimumOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::ArgMaxOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_ArgMaxOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::LessOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_LessOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::NegOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_NegOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::PadV2Options>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_PadV2Options;
+};
+
+template <> struct BuiltinOptionsTraits<circle::GreaterOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_GreaterOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::GreaterEqualOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_GreaterEqualOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::LessEqualOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_LessEqualOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::SelectOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_SelectOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::SliceOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_SliceOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::TransposeConvOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_TransposeConvOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::SparseToDenseOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_SparseToDenseOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::TileOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_TileOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::ExpandDimsOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_ExpandDimsOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::EqualOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_EqualOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::NotEqualOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_NotEqualOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::ShapeOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_ShapeOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::PowOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_PowOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::ArgMinOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_ArgMinOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::FakeQuantOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_FakeQuantOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::PackOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_PackOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::LogicalOrOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_LogicalOrOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::OneHotOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_OneHotOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::LogicalAndOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_LogicalAndOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::LogicalNotOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_LogicalNotOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::UnpackOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_UnpackOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::FloorDivOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_FloorDivOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::SquareOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_SquareOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::ZerosLikeOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_ZerosLikeOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::FillOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_FillOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::BidirectionalSequenceLSTMOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_BidirectionalSequenceLSTMOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::BidirectionalSequenceRNNOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_BidirectionalSequenceRNNOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::UnidirectionalSequenceLSTMOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_UnidirectionalSequenceLSTMOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::FloorModOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_FloorModOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::RangeOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_RangeOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::ResizeNearestNeighborOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_ResizeNearestNeighborOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::LeakyReluOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_LeakyReluOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::SquaredDifferenceOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_SquaredDifferenceOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::MirrorPadOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_MirrorPadOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::AbsOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_AbsOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::SplitVOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_SplitVOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::UniqueOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_UniqueOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::ReverseV2Options>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_ReverseV2Options;
+};
+
+template <> struct BuiltinOptionsTraits<circle::AddNOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_AddNOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::GatherNdOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_GatherNdOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::CosOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_CosOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::WhereOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_WhereOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::RankOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_RankOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::ReverseSequenceOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_ReverseSequenceOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::MatrixDiagOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_MatrixDiagOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::QuantizeOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_QuantizeOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::MatrixSetDiagOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_MatrixSetDiagOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::HardSwishOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_HardSwishOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::IfOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_IfOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::WhileOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_WhileOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::DepthToSpaceOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_DepthToSpaceOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::NonMaxSuppressionV4Options>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_NonMaxSuppressionV4Options;
+};
+
+template <> struct BuiltinOptionsTraits<circle::NonMaxSuppressionV5Options>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_NonMaxSuppressionV5Options;
+};
+
+template <> struct BuiltinOptionsTraits<circle::ScatterNdOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_ScatterNdOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::SelectV2Options>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_SelectV2Options;
+};
+
+template <> struct BuiltinOptionsTraits<circle::DensifyOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_DensifyOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::SegmentSumOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_SegmentSumOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::BatchMatMulOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_BatchMatMulOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::CumsumOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_CumsumOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::CallOnceOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_CallOnceOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::BroadcastToOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_BroadcastToOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::Rfft2dOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_Rfft2dOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::Conv3DOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_Conv3DOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::HashtableOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_HashtableOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::HashtableFindOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_HashtableFindOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::HashtableImportOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_HashtableImportOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::HashtableSizeOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_HashtableSizeOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::VarHandleOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_VarHandleOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::ReadVariableOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_ReadVariableOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::AssignVariableOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_AssignVariableOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::RandomOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_RandomOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::BCQGatherOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_BCQGatherOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::BCQFullyConnectedOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_BCQFullyConnectedOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::InstanceNormOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_InstanceNormOptions;
+};
+
+struct BuiltinOptionsUnion
+{
+ BuiltinOptions type;
+ void *value;
+
+ BuiltinOptionsUnion() : type(BuiltinOptions_NONE), value(nullptr) {}
+ BuiltinOptionsUnion(BuiltinOptionsUnion &&u) FLATBUFFERS_NOEXCEPT : type(BuiltinOptions_NONE),
+ value(nullptr)
+ {
+ std::swap(type, u.type);
+ std::swap(value, u.value);
+ }
+ BuiltinOptionsUnion(const BuiltinOptionsUnion &);
+ BuiltinOptionsUnion &operator=(const BuiltinOptionsUnion &u)
+ {
+ BuiltinOptionsUnion t(u);
+ std::swap(type, t.type);
+ std::swap(value, t.value);
+ return *this;
+ }
+ BuiltinOptionsUnion &operator=(BuiltinOptionsUnion &&u) FLATBUFFERS_NOEXCEPT
+ {
+ std::swap(type, u.type);
+ std::swap(value, u.value);
+ return *this;
+ }
+ ~BuiltinOptionsUnion() { Reset(); }
+
+ void Reset();
+
+#ifndef FLATBUFFERS_CPP98_STL
+ template <typename T> void Set(T &&val)
+ {
+ using RT = typename std::remove_reference<T>::type;
+ Reset();
+ type = BuiltinOptionsTraits<typename RT::TableType>::enum_value;
+ if (type != BuiltinOptions_NONE)
+ {
+ value = new RT(std::forward<T>(val));
+ }
+ }
+#endif // FLATBUFFERS_CPP98_STL
+
+ static void *UnPack(const void *obj, BuiltinOptions type,
+ const flatbuffers::resolver_function_t *resolver);
+ flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr) const;
+
+ circle::Conv2DOptionsT *AsConv2DOptions()
+ {
+ return type == BuiltinOptions_Conv2DOptions ? reinterpret_cast<circle::Conv2DOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::Conv2DOptionsT *AsConv2DOptions() const
+ {
+ return type == BuiltinOptions_Conv2DOptions
+ ? reinterpret_cast<const circle::Conv2DOptionsT *>(value)
+ : nullptr;
+ }
+ circle::DepthwiseConv2DOptionsT *AsDepthwiseConv2DOptions()
+ {
+ return type == BuiltinOptions_DepthwiseConv2DOptions
+ ? reinterpret_cast<circle::DepthwiseConv2DOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::DepthwiseConv2DOptionsT *AsDepthwiseConv2DOptions() const
+ {
+ return type == BuiltinOptions_DepthwiseConv2DOptions
+ ? reinterpret_cast<const circle::DepthwiseConv2DOptionsT *>(value)
+ : nullptr;
+ }
+ circle::ConcatEmbeddingsOptionsT *AsConcatEmbeddingsOptions()
+ {
+ return type == BuiltinOptions_ConcatEmbeddingsOptions
+ ? reinterpret_cast<circle::ConcatEmbeddingsOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::ConcatEmbeddingsOptionsT *AsConcatEmbeddingsOptions() const
+ {
+ return type == BuiltinOptions_ConcatEmbeddingsOptions
+ ? reinterpret_cast<const circle::ConcatEmbeddingsOptionsT *>(value)
+ : nullptr;
+ }
+ circle::LSHProjectionOptionsT *AsLSHProjectionOptions()
+ {
+ return type == BuiltinOptions_LSHProjectionOptions
+ ? reinterpret_cast<circle::LSHProjectionOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::LSHProjectionOptionsT *AsLSHProjectionOptions() const
+ {
+ return type == BuiltinOptions_LSHProjectionOptions
+ ? reinterpret_cast<const circle::LSHProjectionOptionsT *>(value)
+ : nullptr;
+ }
+ circle::Pool2DOptionsT *AsPool2DOptions()
+ {
+ return type == BuiltinOptions_Pool2DOptions ? reinterpret_cast<circle::Pool2DOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::Pool2DOptionsT *AsPool2DOptions() const
+ {
+ return type == BuiltinOptions_Pool2DOptions
+ ? reinterpret_cast<const circle::Pool2DOptionsT *>(value)
+ : nullptr;
+ }
+ circle::SVDFOptionsT *AsSVDFOptions()
+ {
+ return type == BuiltinOptions_SVDFOptions ? reinterpret_cast<circle::SVDFOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::SVDFOptionsT *AsSVDFOptions() const
+ {
+ return type == BuiltinOptions_SVDFOptions
+ ? reinterpret_cast<const circle::SVDFOptionsT *>(value)
+ : nullptr;
+ }
+ circle::RNNOptionsT *AsRNNOptions()
+ {
+ return type == BuiltinOptions_RNNOptions ? reinterpret_cast<circle::RNNOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::RNNOptionsT *AsRNNOptions() const
+ {
+ return type == BuiltinOptions_RNNOptions ? reinterpret_cast<const circle::RNNOptionsT *>(value)
+ : nullptr;
+ }
+ circle::FullyConnectedOptionsT *AsFullyConnectedOptions()
+ {
+ return type == BuiltinOptions_FullyConnectedOptions
+ ? reinterpret_cast<circle::FullyConnectedOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::FullyConnectedOptionsT *AsFullyConnectedOptions() const
+ {
+ return type == BuiltinOptions_FullyConnectedOptions
+ ? reinterpret_cast<const circle::FullyConnectedOptionsT *>(value)
+ : nullptr;
+ }
+ circle::SoftmaxOptionsT *AsSoftmaxOptions()
+ {
+ return type == BuiltinOptions_SoftmaxOptions
+ ? reinterpret_cast<circle::SoftmaxOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::SoftmaxOptionsT *AsSoftmaxOptions() const
+ {
+ return type == BuiltinOptions_SoftmaxOptions
+ ? reinterpret_cast<const circle::SoftmaxOptionsT *>(value)
+ : nullptr;
+ }
+ circle::ConcatenationOptionsT *AsConcatenationOptions()
+ {
+ return type == BuiltinOptions_ConcatenationOptions
+ ? reinterpret_cast<circle::ConcatenationOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::ConcatenationOptionsT *AsConcatenationOptions() const
+ {
+ return type == BuiltinOptions_ConcatenationOptions
+ ? reinterpret_cast<const circle::ConcatenationOptionsT *>(value)
+ : nullptr;
+ }
+ circle::AddOptionsT *AsAddOptions()
+ {
+ return type == BuiltinOptions_AddOptions ? reinterpret_cast<circle::AddOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::AddOptionsT *AsAddOptions() const
+ {
+ return type == BuiltinOptions_AddOptions ? reinterpret_cast<const circle::AddOptionsT *>(value)
+ : nullptr;
+ }
+ circle::L2NormOptionsT *AsL2NormOptions()
+ {
+ return type == BuiltinOptions_L2NormOptions ? reinterpret_cast<circle::L2NormOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::L2NormOptionsT *AsL2NormOptions() const
+ {
+ return type == BuiltinOptions_L2NormOptions
+ ? reinterpret_cast<const circle::L2NormOptionsT *>(value)
+ : nullptr;
+ }
+ circle::LocalResponseNormalizationOptionsT *AsLocalResponseNormalizationOptions()
+ {
+ return type == BuiltinOptions_LocalResponseNormalizationOptions
+ ? reinterpret_cast<circle::LocalResponseNormalizationOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::LocalResponseNormalizationOptionsT *AsLocalResponseNormalizationOptions() const
+ {
+ return type == BuiltinOptions_LocalResponseNormalizationOptions
+ ? reinterpret_cast<const circle::LocalResponseNormalizationOptionsT *>(value)
+ : nullptr;
+ }
+ circle::LSTMOptionsT *AsLSTMOptions()
+ {
+ return type == BuiltinOptions_LSTMOptions ? reinterpret_cast<circle::LSTMOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::LSTMOptionsT *AsLSTMOptions() const
+ {
+ return type == BuiltinOptions_LSTMOptions
+ ? reinterpret_cast<const circle::LSTMOptionsT *>(value)
+ : nullptr;
+ }
+ circle::ResizeBilinearOptionsT *AsResizeBilinearOptions()
+ {
+ return type == BuiltinOptions_ResizeBilinearOptions
+ ? reinterpret_cast<circle::ResizeBilinearOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::ResizeBilinearOptionsT *AsResizeBilinearOptions() const
+ {
+ return type == BuiltinOptions_ResizeBilinearOptions
+ ? reinterpret_cast<const circle::ResizeBilinearOptionsT *>(value)
+ : nullptr;
+ }
+ circle::CallOptionsT *AsCallOptions()
+ {
+ return type == BuiltinOptions_CallOptions ? reinterpret_cast<circle::CallOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::CallOptionsT *AsCallOptions() const
+ {
+ return type == BuiltinOptions_CallOptions
+ ? reinterpret_cast<const circle::CallOptionsT *>(value)
+ : nullptr;
+ }
+ circle::ReshapeOptionsT *AsReshapeOptions()
+ {
+ return type == BuiltinOptions_ReshapeOptions
+ ? reinterpret_cast<circle::ReshapeOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::ReshapeOptionsT *AsReshapeOptions() const
+ {
+ return type == BuiltinOptions_ReshapeOptions
+ ? reinterpret_cast<const circle::ReshapeOptionsT *>(value)
+ : nullptr;
+ }
+ circle::SkipGramOptionsT *AsSkipGramOptions()
+ {
+ return type == BuiltinOptions_SkipGramOptions
+ ? reinterpret_cast<circle::SkipGramOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::SkipGramOptionsT *AsSkipGramOptions() const
+ {
+ return type == BuiltinOptions_SkipGramOptions
+ ? reinterpret_cast<const circle::SkipGramOptionsT *>(value)
+ : nullptr;
+ }
+ circle::SpaceToDepthOptionsT *AsSpaceToDepthOptions()
+ {
+ return type == BuiltinOptions_SpaceToDepthOptions
+ ? reinterpret_cast<circle::SpaceToDepthOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::SpaceToDepthOptionsT *AsSpaceToDepthOptions() const
+ {
+ return type == BuiltinOptions_SpaceToDepthOptions
+ ? reinterpret_cast<const circle::SpaceToDepthOptionsT *>(value)
+ : nullptr;
+ }
+ circle::EmbeddingLookupSparseOptionsT *AsEmbeddingLookupSparseOptions()
+ {
+ return type == BuiltinOptions_EmbeddingLookupSparseOptions
+ ? reinterpret_cast<circle::EmbeddingLookupSparseOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::EmbeddingLookupSparseOptionsT *AsEmbeddingLookupSparseOptions() const
+ {
+ return type == BuiltinOptions_EmbeddingLookupSparseOptions
+ ? reinterpret_cast<const circle::EmbeddingLookupSparseOptionsT *>(value)
+ : nullptr;
+ }
+ circle::MulOptionsT *AsMulOptions()
+ {
+ return type == BuiltinOptions_MulOptions ? reinterpret_cast<circle::MulOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::MulOptionsT *AsMulOptions() const
+ {
+ return type == BuiltinOptions_MulOptions ? reinterpret_cast<const circle::MulOptionsT *>(value)
+ : nullptr;
+ }
+ circle::PadOptionsT *AsPadOptions()
+ {
+ return type == BuiltinOptions_PadOptions ? reinterpret_cast<circle::PadOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::PadOptionsT *AsPadOptions() const
+ {
+ return type == BuiltinOptions_PadOptions ? reinterpret_cast<const circle::PadOptionsT *>(value)
+ : nullptr;
+ }
+ circle::GatherOptionsT *AsGatherOptions()
+ {
+ return type == BuiltinOptions_GatherOptions ? reinterpret_cast<circle::GatherOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::GatherOptionsT *AsGatherOptions() const
+ {
+ return type == BuiltinOptions_GatherOptions
+ ? reinterpret_cast<const circle::GatherOptionsT *>(value)
+ : nullptr;
+ }
+ circle::BatchToSpaceNDOptionsT *AsBatchToSpaceNDOptions()
+ {
+ return type == BuiltinOptions_BatchToSpaceNDOptions
+ ? reinterpret_cast<circle::BatchToSpaceNDOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::BatchToSpaceNDOptionsT *AsBatchToSpaceNDOptions() const
+ {
+ return type == BuiltinOptions_BatchToSpaceNDOptions
+ ? reinterpret_cast<const circle::BatchToSpaceNDOptionsT *>(value)
+ : nullptr;
+ }
+ circle::SpaceToBatchNDOptionsT *AsSpaceToBatchNDOptions()
+ {
+ return type == BuiltinOptions_SpaceToBatchNDOptions
+ ? reinterpret_cast<circle::SpaceToBatchNDOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::SpaceToBatchNDOptionsT *AsSpaceToBatchNDOptions() const
+ {
+ return type == BuiltinOptions_SpaceToBatchNDOptions
+ ? reinterpret_cast<const circle::SpaceToBatchNDOptionsT *>(value)
+ : nullptr;
+ }
+ circle::TransposeOptionsT *AsTransposeOptions()
+ {
+ return type == BuiltinOptions_TransposeOptions
+ ? reinterpret_cast<circle::TransposeOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::TransposeOptionsT *AsTransposeOptions() const
+ {
+ return type == BuiltinOptions_TransposeOptions
+ ? reinterpret_cast<const circle::TransposeOptionsT *>(value)
+ : nullptr;
+ }
+ circle::ReducerOptionsT *AsReducerOptions()
+ {
+ return type == BuiltinOptions_ReducerOptions
+ ? reinterpret_cast<circle::ReducerOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::ReducerOptionsT *AsReducerOptions() const
+ {
+ return type == BuiltinOptions_ReducerOptions
+ ? reinterpret_cast<const circle::ReducerOptionsT *>(value)
+ : nullptr;
+ }
+ circle::SubOptionsT *AsSubOptions()
+ {
+ return type == BuiltinOptions_SubOptions ? reinterpret_cast<circle::SubOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::SubOptionsT *AsSubOptions() const
+ {
+ return type == BuiltinOptions_SubOptions ? reinterpret_cast<const circle::SubOptionsT *>(value)
+ : nullptr;
+ }
+ circle::DivOptionsT *AsDivOptions()
+ {
+ return type == BuiltinOptions_DivOptions ? reinterpret_cast<circle::DivOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::DivOptionsT *AsDivOptions() const
+ {
+ return type == BuiltinOptions_DivOptions ? reinterpret_cast<const circle::DivOptionsT *>(value)
+ : nullptr;
+ }
+ circle::SqueezeOptionsT *AsSqueezeOptions()
+ {
+ return type == BuiltinOptions_SqueezeOptions
+ ? reinterpret_cast<circle::SqueezeOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::SqueezeOptionsT *AsSqueezeOptions() const
+ {
+ return type == BuiltinOptions_SqueezeOptions
+ ? reinterpret_cast<const circle::SqueezeOptionsT *>(value)
+ : nullptr;
+ }
+ circle::SequenceRNNOptionsT *AsSequenceRNNOptions()
+ {
+ return type == BuiltinOptions_SequenceRNNOptions
+ ? reinterpret_cast<circle::SequenceRNNOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::SequenceRNNOptionsT *AsSequenceRNNOptions() const
+ {
+ return type == BuiltinOptions_SequenceRNNOptions
+ ? reinterpret_cast<const circle::SequenceRNNOptionsT *>(value)
+ : nullptr;
+ }
+ circle::StridedSliceOptionsT *AsStridedSliceOptions()
+ {
+ return type == BuiltinOptions_StridedSliceOptions
+ ? reinterpret_cast<circle::StridedSliceOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::StridedSliceOptionsT *AsStridedSliceOptions() const
+ {
+ return type == BuiltinOptions_StridedSliceOptions
+ ? reinterpret_cast<const circle::StridedSliceOptionsT *>(value)
+ : nullptr;
+ }
+ circle::ExpOptionsT *AsExpOptions()
+ {
+ return type == BuiltinOptions_ExpOptions ? reinterpret_cast<circle::ExpOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::ExpOptionsT *AsExpOptions() const
+ {
+ return type == BuiltinOptions_ExpOptions ? reinterpret_cast<const circle::ExpOptionsT *>(value)
+ : nullptr;
+ }
+ circle::TopKV2OptionsT *AsTopKV2Options()
+ {
+ return type == BuiltinOptions_TopKV2Options ? reinterpret_cast<circle::TopKV2OptionsT *>(value)
+ : nullptr;
+ }
+ const circle::TopKV2OptionsT *AsTopKV2Options() const
+ {
+ return type == BuiltinOptions_TopKV2Options
+ ? reinterpret_cast<const circle::TopKV2OptionsT *>(value)
+ : nullptr;
+ }
+ circle::SplitOptionsT *AsSplitOptions()
+ {
+ return type == BuiltinOptions_SplitOptions ? reinterpret_cast<circle::SplitOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::SplitOptionsT *AsSplitOptions() const
+ {
+ return type == BuiltinOptions_SplitOptions
+ ? reinterpret_cast<const circle::SplitOptionsT *>(value)
+ : nullptr;
+ }
+ circle::LogSoftmaxOptionsT *AsLogSoftmaxOptions()
+ {
+ return type == BuiltinOptions_LogSoftmaxOptions
+ ? reinterpret_cast<circle::LogSoftmaxOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::LogSoftmaxOptionsT *AsLogSoftmaxOptions() const
+ {
+ return type == BuiltinOptions_LogSoftmaxOptions
+ ? reinterpret_cast<const circle::LogSoftmaxOptionsT *>(value)
+ : nullptr;
+ }
+ circle::CastOptionsT *AsCastOptions()
+ {
+ return type == BuiltinOptions_CastOptions ? reinterpret_cast<circle::CastOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::CastOptionsT *AsCastOptions() const
+ {
+ return type == BuiltinOptions_CastOptions
+ ? reinterpret_cast<const circle::CastOptionsT *>(value)
+ : nullptr;
+ }
+ circle::DequantizeOptionsT *AsDequantizeOptions()
+ {
+ return type == BuiltinOptions_DequantizeOptions
+ ? reinterpret_cast<circle::DequantizeOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::DequantizeOptionsT *AsDequantizeOptions() const
+ {
+ return type == BuiltinOptions_DequantizeOptions
+ ? reinterpret_cast<const circle::DequantizeOptionsT *>(value)
+ : nullptr;
+ }
+ circle::MaximumMinimumOptionsT *AsMaximumMinimumOptions()
+ {
+ return type == BuiltinOptions_MaximumMinimumOptions
+ ? reinterpret_cast<circle::MaximumMinimumOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::MaximumMinimumOptionsT *AsMaximumMinimumOptions() const
+ {
+ return type == BuiltinOptions_MaximumMinimumOptions
+ ? reinterpret_cast<const circle::MaximumMinimumOptionsT *>(value)
+ : nullptr;
+ }
+ circle::ArgMaxOptionsT *AsArgMaxOptions()
+ {
+ return type == BuiltinOptions_ArgMaxOptions ? reinterpret_cast<circle::ArgMaxOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::ArgMaxOptionsT *AsArgMaxOptions() const
+ {
+ return type == BuiltinOptions_ArgMaxOptions
+ ? reinterpret_cast<const circle::ArgMaxOptionsT *>(value)
+ : nullptr;
+ }
+ circle::LessOptionsT *AsLessOptions()
+ {
+ return type == BuiltinOptions_LessOptions ? reinterpret_cast<circle::LessOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::LessOptionsT *AsLessOptions() const
+ {
+ return type == BuiltinOptions_LessOptions
+ ? reinterpret_cast<const circle::LessOptionsT *>(value)
+ : nullptr;
+ }
+ circle::NegOptionsT *AsNegOptions()
+ {
+ return type == BuiltinOptions_NegOptions ? reinterpret_cast<circle::NegOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::NegOptionsT *AsNegOptions() const
+ {
+ return type == BuiltinOptions_NegOptions ? reinterpret_cast<const circle::NegOptionsT *>(value)
+ : nullptr;
+ }
+ circle::PadV2OptionsT *AsPadV2Options()
+ {
+ return type == BuiltinOptions_PadV2Options ? reinterpret_cast<circle::PadV2OptionsT *>(value)
+ : nullptr;
+ }
+ const circle::PadV2OptionsT *AsPadV2Options() const
+ {
+ return type == BuiltinOptions_PadV2Options
+ ? reinterpret_cast<const circle::PadV2OptionsT *>(value)
+ : nullptr;
+ }
+ circle::GreaterOptionsT *AsGreaterOptions()
+ {
+ return type == BuiltinOptions_GreaterOptions
+ ? reinterpret_cast<circle::GreaterOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::GreaterOptionsT *AsGreaterOptions() const
+ {
+ return type == BuiltinOptions_GreaterOptions
+ ? reinterpret_cast<const circle::GreaterOptionsT *>(value)
+ : nullptr;
+ }
+ circle::GreaterEqualOptionsT *AsGreaterEqualOptions()
+ {
+ return type == BuiltinOptions_GreaterEqualOptions
+ ? reinterpret_cast<circle::GreaterEqualOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::GreaterEqualOptionsT *AsGreaterEqualOptions() const
+ {
+ return type == BuiltinOptions_GreaterEqualOptions
+ ? reinterpret_cast<const circle::GreaterEqualOptionsT *>(value)
+ : nullptr;
+ }
+ circle::LessEqualOptionsT *AsLessEqualOptions()
+ {
+ return type == BuiltinOptions_LessEqualOptions
+ ? reinterpret_cast<circle::LessEqualOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::LessEqualOptionsT *AsLessEqualOptions() const
+ {
+ return type == BuiltinOptions_LessEqualOptions
+ ? reinterpret_cast<const circle::LessEqualOptionsT *>(value)
+ : nullptr;
+ }
+ circle::SelectOptionsT *AsSelectOptions()
+ {
+ return type == BuiltinOptions_SelectOptions ? reinterpret_cast<circle::SelectOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::SelectOptionsT *AsSelectOptions() const
+ {
+ return type == BuiltinOptions_SelectOptions
+ ? reinterpret_cast<const circle::SelectOptionsT *>(value)
+ : nullptr;
+ }
+ circle::SliceOptionsT *AsSliceOptions()
+ {
+ return type == BuiltinOptions_SliceOptions ? reinterpret_cast<circle::SliceOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::SliceOptionsT *AsSliceOptions() const
+ {
+ return type == BuiltinOptions_SliceOptions
+ ? reinterpret_cast<const circle::SliceOptionsT *>(value)
+ : nullptr;
+ }
+ circle::TransposeConvOptionsT *AsTransposeConvOptions()
+ {
+ return type == BuiltinOptions_TransposeConvOptions
+ ? reinterpret_cast<circle::TransposeConvOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::TransposeConvOptionsT *AsTransposeConvOptions() const
+ {
+ return type == BuiltinOptions_TransposeConvOptions
+ ? reinterpret_cast<const circle::TransposeConvOptionsT *>(value)
+ : nullptr;
+ }
+ circle::SparseToDenseOptionsT *AsSparseToDenseOptions()
+ {
+ return type == BuiltinOptions_SparseToDenseOptions
+ ? reinterpret_cast<circle::SparseToDenseOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::SparseToDenseOptionsT *AsSparseToDenseOptions() const
+ {
+ return type == BuiltinOptions_SparseToDenseOptions
+ ? reinterpret_cast<const circle::SparseToDenseOptionsT *>(value)
+ : nullptr;
+ }
+ circle::TileOptionsT *AsTileOptions()
+ {
+ return type == BuiltinOptions_TileOptions ? reinterpret_cast<circle::TileOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::TileOptionsT *AsTileOptions() const
+ {
+ return type == BuiltinOptions_TileOptions
+ ? reinterpret_cast<const circle::TileOptionsT *>(value)
+ : nullptr;
+ }
+ circle::ExpandDimsOptionsT *AsExpandDimsOptions()
+ {
+ return type == BuiltinOptions_ExpandDimsOptions
+ ? reinterpret_cast<circle::ExpandDimsOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::ExpandDimsOptionsT *AsExpandDimsOptions() const
+ {
+ return type == BuiltinOptions_ExpandDimsOptions
+ ? reinterpret_cast<const circle::ExpandDimsOptionsT *>(value)
+ : nullptr;
+ }
+ circle::EqualOptionsT *AsEqualOptions()
+ {
+ return type == BuiltinOptions_EqualOptions ? reinterpret_cast<circle::EqualOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::EqualOptionsT *AsEqualOptions() const
+ {
+ return type == BuiltinOptions_EqualOptions
+ ? reinterpret_cast<const circle::EqualOptionsT *>(value)
+ : nullptr;
+ }
+ circle::NotEqualOptionsT *AsNotEqualOptions()
+ {
+ return type == BuiltinOptions_NotEqualOptions
+ ? reinterpret_cast<circle::NotEqualOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::NotEqualOptionsT *AsNotEqualOptions() const
+ {
+ return type == BuiltinOptions_NotEqualOptions
+ ? reinterpret_cast<const circle::NotEqualOptionsT *>(value)
+ : nullptr;
+ }
+ circle::ShapeOptionsT *AsShapeOptions()
+ {
+ return type == BuiltinOptions_ShapeOptions ? reinterpret_cast<circle::ShapeOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::ShapeOptionsT *AsShapeOptions() const
+ {
+ return type == BuiltinOptions_ShapeOptions
+ ? reinterpret_cast<const circle::ShapeOptionsT *>(value)
+ : nullptr;
+ }
+ circle::PowOptionsT *AsPowOptions()
+ {
+ return type == BuiltinOptions_PowOptions ? reinterpret_cast<circle::PowOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::PowOptionsT *AsPowOptions() const
+ {
+ return type == BuiltinOptions_PowOptions ? reinterpret_cast<const circle::PowOptionsT *>(value)
+ : nullptr;
+ }
+ circle::ArgMinOptionsT *AsArgMinOptions()
+ {
+ return type == BuiltinOptions_ArgMinOptions ? reinterpret_cast<circle::ArgMinOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::ArgMinOptionsT *AsArgMinOptions() const
+ {
+ return type == BuiltinOptions_ArgMinOptions
+ ? reinterpret_cast<const circle::ArgMinOptionsT *>(value)
+ : nullptr;
+ }
+ circle::FakeQuantOptionsT *AsFakeQuantOptions()
+ {
+ return type == BuiltinOptions_FakeQuantOptions
+ ? reinterpret_cast<circle::FakeQuantOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::FakeQuantOptionsT *AsFakeQuantOptions() const
+ {
+ return type == BuiltinOptions_FakeQuantOptions
+ ? reinterpret_cast<const circle::FakeQuantOptionsT *>(value)
+ : nullptr;
+ }
+ circle::PackOptionsT *AsPackOptions()
+ {
+ return type == BuiltinOptions_PackOptions ? reinterpret_cast<circle::PackOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::PackOptionsT *AsPackOptions() const
+ {
+ return type == BuiltinOptions_PackOptions
+ ? reinterpret_cast<const circle::PackOptionsT *>(value)
+ : nullptr;
+ }
+ circle::LogicalOrOptionsT *AsLogicalOrOptions()
+ {
+ return type == BuiltinOptions_LogicalOrOptions
+ ? reinterpret_cast<circle::LogicalOrOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::LogicalOrOptionsT *AsLogicalOrOptions() const
+ {
+ return type == BuiltinOptions_LogicalOrOptions
+ ? reinterpret_cast<const circle::LogicalOrOptionsT *>(value)
+ : nullptr;
+ }
+ circle::OneHotOptionsT *AsOneHotOptions()
+ {
+ return type == BuiltinOptions_OneHotOptions ? reinterpret_cast<circle::OneHotOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::OneHotOptionsT *AsOneHotOptions() const
+ {
+ return type == BuiltinOptions_OneHotOptions
+ ? reinterpret_cast<const circle::OneHotOptionsT *>(value)
+ : nullptr;
+ }
+ circle::LogicalAndOptionsT *AsLogicalAndOptions()
+ {
+ return type == BuiltinOptions_LogicalAndOptions
+ ? reinterpret_cast<circle::LogicalAndOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::LogicalAndOptionsT *AsLogicalAndOptions() const
+ {
+ return type == BuiltinOptions_LogicalAndOptions
+ ? reinterpret_cast<const circle::LogicalAndOptionsT *>(value)
+ : nullptr;
+ }
+ circle::LogicalNotOptionsT *AsLogicalNotOptions()
+ {
+ return type == BuiltinOptions_LogicalNotOptions
+ ? reinterpret_cast<circle::LogicalNotOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::LogicalNotOptionsT *AsLogicalNotOptions() const
+ {
+ return type == BuiltinOptions_LogicalNotOptions
+ ? reinterpret_cast<const circle::LogicalNotOptionsT *>(value)
+ : nullptr;
+ }
+ circle::UnpackOptionsT *AsUnpackOptions()
+ {
+ return type == BuiltinOptions_UnpackOptions ? reinterpret_cast<circle::UnpackOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::UnpackOptionsT *AsUnpackOptions() const
+ {
+ return type == BuiltinOptions_UnpackOptions
+ ? reinterpret_cast<const circle::UnpackOptionsT *>(value)
+ : nullptr;
+ }
+ circle::FloorDivOptionsT *AsFloorDivOptions()
+ {
+ return type == BuiltinOptions_FloorDivOptions
+ ? reinterpret_cast<circle::FloorDivOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::FloorDivOptionsT *AsFloorDivOptions() const
+ {
+ return type == BuiltinOptions_FloorDivOptions
+ ? reinterpret_cast<const circle::FloorDivOptionsT *>(value)
+ : nullptr;
+ }
+ circle::SquareOptionsT *AsSquareOptions()
+ {
+ return type == BuiltinOptions_SquareOptions ? reinterpret_cast<circle::SquareOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::SquareOptionsT *AsSquareOptions() const
+ {
+ return type == BuiltinOptions_SquareOptions
+ ? reinterpret_cast<const circle::SquareOptionsT *>(value)
+ : nullptr;
+ }
+ circle::ZerosLikeOptionsT *AsZerosLikeOptions()
+ {
+ return type == BuiltinOptions_ZerosLikeOptions
+ ? reinterpret_cast<circle::ZerosLikeOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::ZerosLikeOptionsT *AsZerosLikeOptions() const
+ {
+ return type == BuiltinOptions_ZerosLikeOptions
+ ? reinterpret_cast<const circle::ZerosLikeOptionsT *>(value)
+ : nullptr;
+ }
+ circle::FillOptionsT *AsFillOptions()
+ {
+ return type == BuiltinOptions_FillOptions ? reinterpret_cast<circle::FillOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::FillOptionsT *AsFillOptions() const
+ {
+ return type == BuiltinOptions_FillOptions
+ ? reinterpret_cast<const circle::FillOptionsT *>(value)
+ : nullptr;
+ }
+ circle::BidirectionalSequenceLSTMOptionsT *AsBidirectionalSequenceLSTMOptions()
+ {
+ return type == BuiltinOptions_BidirectionalSequenceLSTMOptions
+ ? reinterpret_cast<circle::BidirectionalSequenceLSTMOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::BidirectionalSequenceLSTMOptionsT *AsBidirectionalSequenceLSTMOptions() const
+ {
+ return type == BuiltinOptions_BidirectionalSequenceLSTMOptions
+ ? reinterpret_cast<const circle::BidirectionalSequenceLSTMOptionsT *>(value)
+ : nullptr;
+ }
+ circle::BidirectionalSequenceRNNOptionsT *AsBidirectionalSequenceRNNOptions()
+ {
+ return type == BuiltinOptions_BidirectionalSequenceRNNOptions
+ ? reinterpret_cast<circle::BidirectionalSequenceRNNOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::BidirectionalSequenceRNNOptionsT *AsBidirectionalSequenceRNNOptions() const
+ {
+ return type == BuiltinOptions_BidirectionalSequenceRNNOptions
+ ? reinterpret_cast<const circle::BidirectionalSequenceRNNOptionsT *>(value)
+ : nullptr;
+ }
+ circle::UnidirectionalSequenceLSTMOptionsT *AsUnidirectionalSequenceLSTMOptions()
+ {
+ return type == BuiltinOptions_UnidirectionalSequenceLSTMOptions
+ ? reinterpret_cast<circle::UnidirectionalSequenceLSTMOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::UnidirectionalSequenceLSTMOptionsT *AsUnidirectionalSequenceLSTMOptions() const
+ {
+ return type == BuiltinOptions_UnidirectionalSequenceLSTMOptions
+ ? reinterpret_cast<const circle::UnidirectionalSequenceLSTMOptionsT *>(value)
+ : nullptr;
+ }
+ circle::FloorModOptionsT *AsFloorModOptions()
+ {
+ return type == BuiltinOptions_FloorModOptions
+ ? reinterpret_cast<circle::FloorModOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::FloorModOptionsT *AsFloorModOptions() const
+ {
+ return type == BuiltinOptions_FloorModOptions
+ ? reinterpret_cast<const circle::FloorModOptionsT *>(value)
+ : nullptr;
+ }
+ circle::RangeOptionsT *AsRangeOptions()
+ {
+ return type == BuiltinOptions_RangeOptions ? reinterpret_cast<circle::RangeOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::RangeOptionsT *AsRangeOptions() const
+ {
+ return type == BuiltinOptions_RangeOptions
+ ? reinterpret_cast<const circle::RangeOptionsT *>(value)
+ : nullptr;
+ }
+ circle::ResizeNearestNeighborOptionsT *AsResizeNearestNeighborOptions()
+ {
+ return type == BuiltinOptions_ResizeNearestNeighborOptions
+ ? reinterpret_cast<circle::ResizeNearestNeighborOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::ResizeNearestNeighborOptionsT *AsResizeNearestNeighborOptions() const
+ {
+ return type == BuiltinOptions_ResizeNearestNeighborOptions
+ ? reinterpret_cast<const circle::ResizeNearestNeighborOptionsT *>(value)
+ : nullptr;
+ }
+ circle::LeakyReluOptionsT *AsLeakyReluOptions()
+ {
+ return type == BuiltinOptions_LeakyReluOptions
+ ? reinterpret_cast<circle::LeakyReluOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::LeakyReluOptionsT *AsLeakyReluOptions() const
+ {
+ return type == BuiltinOptions_LeakyReluOptions
+ ? reinterpret_cast<const circle::LeakyReluOptionsT *>(value)
+ : nullptr;
+ }
+ circle::SquaredDifferenceOptionsT *AsSquaredDifferenceOptions()
+ {
+ return type == BuiltinOptions_SquaredDifferenceOptions
+ ? reinterpret_cast<circle::SquaredDifferenceOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::SquaredDifferenceOptionsT *AsSquaredDifferenceOptions() const
+ {
+ return type == BuiltinOptions_SquaredDifferenceOptions
+ ? reinterpret_cast<const circle::SquaredDifferenceOptionsT *>(value)
+ : nullptr;
+ }
+ circle::MirrorPadOptionsT *AsMirrorPadOptions()
+ {
+ return type == BuiltinOptions_MirrorPadOptions
+ ? reinterpret_cast<circle::MirrorPadOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::MirrorPadOptionsT *AsMirrorPadOptions() const
+ {
+ return type == BuiltinOptions_MirrorPadOptions
+ ? reinterpret_cast<const circle::MirrorPadOptionsT *>(value)
+ : nullptr;
+ }
+ circle::AbsOptionsT *AsAbsOptions()
+ {
+ return type == BuiltinOptions_AbsOptions ? reinterpret_cast<circle::AbsOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::AbsOptionsT *AsAbsOptions() const
+ {
+ return type == BuiltinOptions_AbsOptions ? reinterpret_cast<const circle::AbsOptionsT *>(value)
+ : nullptr;
+ }
+ circle::SplitVOptionsT *AsSplitVOptions()
+ {
+ return type == BuiltinOptions_SplitVOptions ? reinterpret_cast<circle::SplitVOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::SplitVOptionsT *AsSplitVOptions() const
+ {
+ return type == BuiltinOptions_SplitVOptions
+ ? reinterpret_cast<const circle::SplitVOptionsT *>(value)
+ : nullptr;
+ }
+ circle::UniqueOptionsT *AsUniqueOptions()
+ {
+ return type == BuiltinOptions_UniqueOptions ? reinterpret_cast<circle::UniqueOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::UniqueOptionsT *AsUniqueOptions() const
+ {
+ return type == BuiltinOptions_UniqueOptions
+ ? reinterpret_cast<const circle::UniqueOptionsT *>(value)
+ : nullptr;
+ }
+ circle::ReverseV2OptionsT *AsReverseV2Options()
+ {
+ return type == BuiltinOptions_ReverseV2Options
+ ? reinterpret_cast<circle::ReverseV2OptionsT *>(value)
+ : nullptr;
+ }
+ const circle::ReverseV2OptionsT *AsReverseV2Options() const
+ {
+ return type == BuiltinOptions_ReverseV2Options
+ ? reinterpret_cast<const circle::ReverseV2OptionsT *>(value)
+ : nullptr;
+ }
+ circle::AddNOptionsT *AsAddNOptions()
+ {
+ return type == BuiltinOptions_AddNOptions ? reinterpret_cast<circle::AddNOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::AddNOptionsT *AsAddNOptions() const
+ {
+ return type == BuiltinOptions_AddNOptions
+ ? reinterpret_cast<const circle::AddNOptionsT *>(value)
+ : nullptr;
+ }
+ circle::GatherNdOptionsT *AsGatherNdOptions()
+ {
+ return type == BuiltinOptions_GatherNdOptions
+ ? reinterpret_cast<circle::GatherNdOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::GatherNdOptionsT *AsGatherNdOptions() const
+ {
+ return type == BuiltinOptions_GatherNdOptions
+ ? reinterpret_cast<const circle::GatherNdOptionsT *>(value)
+ : nullptr;
+ }
+ circle::CosOptionsT *AsCosOptions()
+ {
+ return type == BuiltinOptions_CosOptions ? reinterpret_cast<circle::CosOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::CosOptionsT *AsCosOptions() const
+ {
+ return type == BuiltinOptions_CosOptions ? reinterpret_cast<const circle::CosOptionsT *>(value)
+ : nullptr;
+ }
+ circle::WhereOptionsT *AsWhereOptions()
+ {
+ return type == BuiltinOptions_WhereOptions ? reinterpret_cast<circle::WhereOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::WhereOptionsT *AsWhereOptions() const
+ {
+ return type == BuiltinOptions_WhereOptions
+ ? reinterpret_cast<const circle::WhereOptionsT *>(value)
+ : nullptr;
+ }
+ circle::RankOptionsT *AsRankOptions()
+ {
+ return type == BuiltinOptions_RankOptions ? reinterpret_cast<circle::RankOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::RankOptionsT *AsRankOptions() const
+ {
+ return type == BuiltinOptions_RankOptions
+ ? reinterpret_cast<const circle::RankOptionsT *>(value)
+ : nullptr;
+ }
+ circle::ReverseSequenceOptionsT *AsReverseSequenceOptions()
+ {
+ return type == BuiltinOptions_ReverseSequenceOptions
+ ? reinterpret_cast<circle::ReverseSequenceOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::ReverseSequenceOptionsT *AsReverseSequenceOptions() const
+ {
+ return type == BuiltinOptions_ReverseSequenceOptions
+ ? reinterpret_cast<const circle::ReverseSequenceOptionsT *>(value)
+ : nullptr;
+ }
+ circle::MatrixDiagOptionsT *AsMatrixDiagOptions()
+ {
+ return type == BuiltinOptions_MatrixDiagOptions
+ ? reinterpret_cast<circle::MatrixDiagOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::MatrixDiagOptionsT *AsMatrixDiagOptions() const
+ {
+ return type == BuiltinOptions_MatrixDiagOptions
+ ? reinterpret_cast<const circle::MatrixDiagOptionsT *>(value)
+ : nullptr;
+ }
+ circle::QuantizeOptionsT *AsQuantizeOptions()
+ {
+ return type == BuiltinOptions_QuantizeOptions
+ ? reinterpret_cast<circle::QuantizeOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::QuantizeOptionsT *AsQuantizeOptions() const
+ {
+ return type == BuiltinOptions_QuantizeOptions
+ ? reinterpret_cast<const circle::QuantizeOptionsT *>(value)
+ : nullptr;
+ }
+ circle::MatrixSetDiagOptionsT *AsMatrixSetDiagOptions()
+ {
+ return type == BuiltinOptions_MatrixSetDiagOptions
+ ? reinterpret_cast<circle::MatrixSetDiagOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::MatrixSetDiagOptionsT *AsMatrixSetDiagOptions() const
+ {
+ return type == BuiltinOptions_MatrixSetDiagOptions
+ ? reinterpret_cast<const circle::MatrixSetDiagOptionsT *>(value)
+ : nullptr;
+ }
+ circle::HardSwishOptionsT *AsHardSwishOptions()
+ {
+ return type == BuiltinOptions_HardSwishOptions
+ ? reinterpret_cast<circle::HardSwishOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::HardSwishOptionsT *AsHardSwishOptions() const
+ {
+ return type == BuiltinOptions_HardSwishOptions
+ ? reinterpret_cast<const circle::HardSwishOptionsT *>(value)
+ : nullptr;
+ }
+ circle::IfOptionsT *AsIfOptions()
+ {
+ return type == BuiltinOptions_IfOptions ? reinterpret_cast<circle::IfOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::IfOptionsT *AsIfOptions() const
+ {
+ return type == BuiltinOptions_IfOptions ? reinterpret_cast<const circle::IfOptionsT *>(value)
+ : nullptr;
+ }
+ circle::WhileOptionsT *AsWhileOptions()
+ {
+ return type == BuiltinOptions_WhileOptions ? reinterpret_cast<circle::WhileOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::WhileOptionsT *AsWhileOptions() const
+ {
+ return type == BuiltinOptions_WhileOptions
+ ? reinterpret_cast<const circle::WhileOptionsT *>(value)
+ : nullptr;
+ }
+ circle::DepthToSpaceOptionsT *AsDepthToSpaceOptions()
+ {
+ return type == BuiltinOptions_DepthToSpaceOptions
+ ? reinterpret_cast<circle::DepthToSpaceOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::DepthToSpaceOptionsT *AsDepthToSpaceOptions() const
+ {
+ return type == BuiltinOptions_DepthToSpaceOptions
+ ? reinterpret_cast<const circle::DepthToSpaceOptionsT *>(value)
+ : nullptr;
+ }
+ circle::NonMaxSuppressionV4OptionsT *AsNonMaxSuppressionV4Options()
+ {
+ return type == BuiltinOptions_NonMaxSuppressionV4Options
+ ? reinterpret_cast<circle::NonMaxSuppressionV4OptionsT *>(value)
+ : nullptr;
+ }
+ const circle::NonMaxSuppressionV4OptionsT *AsNonMaxSuppressionV4Options() const
+ {
+ return type == BuiltinOptions_NonMaxSuppressionV4Options
+ ? reinterpret_cast<const circle::NonMaxSuppressionV4OptionsT *>(value)
+ : nullptr;
+ }
+ circle::NonMaxSuppressionV5OptionsT *AsNonMaxSuppressionV5Options()
+ {
+ return type == BuiltinOptions_NonMaxSuppressionV5Options
+ ? reinterpret_cast<circle::NonMaxSuppressionV5OptionsT *>(value)
+ : nullptr;
+ }
+ const circle::NonMaxSuppressionV5OptionsT *AsNonMaxSuppressionV5Options() const
+ {
+ return type == BuiltinOptions_NonMaxSuppressionV5Options
+ ? reinterpret_cast<const circle::NonMaxSuppressionV5OptionsT *>(value)
+ : nullptr;
+ }
+ circle::ScatterNdOptionsT *AsScatterNdOptions()
+ {
+ return type == BuiltinOptions_ScatterNdOptions
+ ? reinterpret_cast<circle::ScatterNdOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::ScatterNdOptionsT *AsScatterNdOptions() const
+ {
+ return type == BuiltinOptions_ScatterNdOptions
+ ? reinterpret_cast<const circle::ScatterNdOptionsT *>(value)
+ : nullptr;
+ }
+ circle::SelectV2OptionsT *AsSelectV2Options()
+ {
+ return type == BuiltinOptions_SelectV2Options
+ ? reinterpret_cast<circle::SelectV2OptionsT *>(value)
+ : nullptr;
+ }
+ const circle::SelectV2OptionsT *AsSelectV2Options() const
+ {
+ return type == BuiltinOptions_SelectV2Options
+ ? reinterpret_cast<const circle::SelectV2OptionsT *>(value)
+ : nullptr;
+ }
+ circle::DensifyOptionsT *AsDensifyOptions()
+ {
+ return type == BuiltinOptions_DensifyOptions
+ ? reinterpret_cast<circle::DensifyOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::DensifyOptionsT *AsDensifyOptions() const
+ {
+ return type == BuiltinOptions_DensifyOptions
+ ? reinterpret_cast<const circle::DensifyOptionsT *>(value)
+ : nullptr;
+ }
+ circle::SegmentSumOptionsT *AsSegmentSumOptions()
+ {
+ return type == BuiltinOptions_SegmentSumOptions
+ ? reinterpret_cast<circle::SegmentSumOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::SegmentSumOptionsT *AsSegmentSumOptions() const
+ {
+ return type == BuiltinOptions_SegmentSumOptions
+ ? reinterpret_cast<const circle::SegmentSumOptionsT *>(value)
+ : nullptr;
+ }
+ circle::BatchMatMulOptionsT *AsBatchMatMulOptions()
+ {
+ return type == BuiltinOptions_BatchMatMulOptions
+ ? reinterpret_cast<circle::BatchMatMulOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::BatchMatMulOptionsT *AsBatchMatMulOptions() const
+ {
+ return type == BuiltinOptions_BatchMatMulOptions
+ ? reinterpret_cast<const circle::BatchMatMulOptionsT *>(value)
+ : nullptr;
+ }
+ circle::CumsumOptionsT *AsCumsumOptions()
+ {
+ return type == BuiltinOptions_CumsumOptions ? reinterpret_cast<circle::CumsumOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::CumsumOptionsT *AsCumsumOptions() const
+ {
+ return type == BuiltinOptions_CumsumOptions
+ ? reinterpret_cast<const circle::CumsumOptionsT *>(value)
+ : nullptr;
+ }
+ circle::CallOnceOptionsT *AsCallOnceOptions()
+ {
+ return type == BuiltinOptions_CallOnceOptions
+ ? reinterpret_cast<circle::CallOnceOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::CallOnceOptionsT *AsCallOnceOptions() const
+ {
+ return type == BuiltinOptions_CallOnceOptions
+ ? reinterpret_cast<const circle::CallOnceOptionsT *>(value)
+ : nullptr;
+ }
+ circle::BroadcastToOptionsT *AsBroadcastToOptions()
+ {
+ return type == BuiltinOptions_BroadcastToOptions
+ ? reinterpret_cast<circle::BroadcastToOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::BroadcastToOptionsT *AsBroadcastToOptions() const
+ {
+ return type == BuiltinOptions_BroadcastToOptions
+ ? reinterpret_cast<const circle::BroadcastToOptionsT *>(value)
+ : nullptr;
+ }
+ circle::Rfft2dOptionsT *AsRfft2dOptions()
+ {
+ return type == BuiltinOptions_Rfft2dOptions ? reinterpret_cast<circle::Rfft2dOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::Rfft2dOptionsT *AsRfft2dOptions() const
+ {
+ return type == BuiltinOptions_Rfft2dOptions
+ ? reinterpret_cast<const circle::Rfft2dOptionsT *>(value)
+ : nullptr;
+ }
+ circle::Conv3DOptionsT *AsConv3DOptions()
+ {
+ return type == BuiltinOptions_Conv3DOptions ? reinterpret_cast<circle::Conv3DOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::Conv3DOptionsT *AsConv3DOptions() const
+ {
+ return type == BuiltinOptions_Conv3DOptions
+ ? reinterpret_cast<const circle::Conv3DOptionsT *>(value)
+ : nullptr;
+ }
+ circle::HashtableOptionsT *AsHashtableOptions()
+ {
+ return type == BuiltinOptions_HashtableOptions
+ ? reinterpret_cast<circle::HashtableOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::HashtableOptionsT *AsHashtableOptions() const
+ {
+ return type == BuiltinOptions_HashtableOptions
+ ? reinterpret_cast<const circle::HashtableOptionsT *>(value)
+ : nullptr;
+ }
+ circle::HashtableFindOptionsT *AsHashtableFindOptions()
+ {
+ return type == BuiltinOptions_HashtableFindOptions
+ ? reinterpret_cast<circle::HashtableFindOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::HashtableFindOptionsT *AsHashtableFindOptions() const
+ {
+ return type == BuiltinOptions_HashtableFindOptions
+ ? reinterpret_cast<const circle::HashtableFindOptionsT *>(value)
+ : nullptr;
+ }
+ circle::HashtableImportOptionsT *AsHashtableImportOptions()
+ {
+ return type == BuiltinOptions_HashtableImportOptions
+ ? reinterpret_cast<circle::HashtableImportOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::HashtableImportOptionsT *AsHashtableImportOptions() const
+ {
+ return type == BuiltinOptions_HashtableImportOptions
+ ? reinterpret_cast<const circle::HashtableImportOptionsT *>(value)
+ : nullptr;
+ }
+ circle::HashtableSizeOptionsT *AsHashtableSizeOptions()
+ {
+ return type == BuiltinOptions_HashtableSizeOptions
+ ? reinterpret_cast<circle::HashtableSizeOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::HashtableSizeOptionsT *AsHashtableSizeOptions() const
+ {
+ return type == BuiltinOptions_HashtableSizeOptions
+ ? reinterpret_cast<const circle::HashtableSizeOptionsT *>(value)
+ : nullptr;
+ }
+ circle::VarHandleOptionsT *AsVarHandleOptions()
+ {
+ return type == BuiltinOptions_VarHandleOptions
+ ? reinterpret_cast<circle::VarHandleOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::VarHandleOptionsT *AsVarHandleOptions() const
+ {
+ return type == BuiltinOptions_VarHandleOptions
+ ? reinterpret_cast<const circle::VarHandleOptionsT *>(value)
+ : nullptr;
+ }
+ circle::ReadVariableOptionsT *AsReadVariableOptions()
+ {
+ return type == BuiltinOptions_ReadVariableOptions
+ ? reinterpret_cast<circle::ReadVariableOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::ReadVariableOptionsT *AsReadVariableOptions() const
+ {
+ return type == BuiltinOptions_ReadVariableOptions
+ ? reinterpret_cast<const circle::ReadVariableOptionsT *>(value)
+ : nullptr;
+ }
+ circle::AssignVariableOptionsT *AsAssignVariableOptions()
+ {
+ return type == BuiltinOptions_AssignVariableOptions
+ ? reinterpret_cast<circle::AssignVariableOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::AssignVariableOptionsT *AsAssignVariableOptions() const
+ {
+ return type == BuiltinOptions_AssignVariableOptions
+ ? reinterpret_cast<const circle::AssignVariableOptionsT *>(value)
+ : nullptr;
+ }
+ circle::RandomOptionsT *AsRandomOptions()
+ {
+ return type == BuiltinOptions_RandomOptions ? reinterpret_cast<circle::RandomOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::RandomOptionsT *AsRandomOptions() const
+ {
+ return type == BuiltinOptions_RandomOptions
+ ? reinterpret_cast<const circle::RandomOptionsT *>(value)
+ : nullptr;
+ }
+ circle::BCQGatherOptionsT *AsBCQGatherOptions()
+ {
+ return type == BuiltinOptions_BCQGatherOptions
+ ? reinterpret_cast<circle::BCQGatherOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::BCQGatherOptionsT *AsBCQGatherOptions() const
+ {
+ return type == BuiltinOptions_BCQGatherOptions
+ ? reinterpret_cast<const circle::BCQGatherOptionsT *>(value)
+ : nullptr;
+ }
+ circle::BCQFullyConnectedOptionsT *AsBCQFullyConnectedOptions()
+ {
+ return type == BuiltinOptions_BCQFullyConnectedOptions
+ ? reinterpret_cast<circle::BCQFullyConnectedOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::BCQFullyConnectedOptionsT *AsBCQFullyConnectedOptions() const
+ {
+ return type == BuiltinOptions_BCQFullyConnectedOptions
+ ? reinterpret_cast<const circle::BCQFullyConnectedOptionsT *>(value)
+ : nullptr;
+ }
+ circle::InstanceNormOptionsT *AsInstanceNormOptions()
+ {
+ return type == BuiltinOptions_InstanceNormOptions
+ ? reinterpret_cast<circle::InstanceNormOptionsT *>(value)
+ : nullptr;
+ }
+ const circle::InstanceNormOptionsT *AsInstanceNormOptions() const
+ {
+ return type == BuiltinOptions_InstanceNormOptions
+ ? reinterpret_cast<const circle::InstanceNormOptionsT *>(value)
+ : nullptr;
+ }
+};
+
+bool VerifyBuiltinOptions(flatbuffers::Verifier &verifier, const void *obj, BuiltinOptions type);
+bool VerifyBuiltinOptionsVector(flatbuffers::Verifier &verifier,
+ const flatbuffers::Vector<flatbuffers::Offset<void>> *values,
+ const flatbuffers::Vector<uint8_t> *types);
+
+enum Padding : int8_t
+{
+ Padding_SAME = 0,
+ Padding_VALID = 1,
+ Padding_MIN = Padding_SAME,
+ Padding_MAX = Padding_VALID
+};
+
+inline const Padding (&EnumValuesPadding())[2]
+{
+ static const Padding values[] = {Padding_SAME, Padding_VALID};
+ return values;
+}
+
+inline const char *const *EnumNamesPadding()
+{
+ static const char *const names[3] = {"SAME", "VALID", nullptr};
+ return names;
+}
+
+inline const char *EnumNamePadding(Padding e)
+{
+ if (flatbuffers::IsOutRange(e, Padding_SAME, Padding_VALID))
+ return "";
+ const size_t index = static_cast<size_t>(e);
+ return EnumNamesPadding()[index];
+}
+
+enum ActivationFunctionType : int8_t
+{
+ ActivationFunctionType_NONE = 0,
+ ActivationFunctionType_RELU = 1,
+ ActivationFunctionType_RELU_N1_TO_1 = 2,
+ ActivationFunctionType_RELU6 = 3,
+ ActivationFunctionType_TANH = 4,
+ ActivationFunctionType_SIGN_BIT = 5,
+ ActivationFunctionType_MIN = ActivationFunctionType_NONE,
+ ActivationFunctionType_MAX = ActivationFunctionType_SIGN_BIT
+};
+
+inline const ActivationFunctionType (&EnumValuesActivationFunctionType())[6]
+{
+ static const ActivationFunctionType values[] = {
+ ActivationFunctionType_NONE, ActivationFunctionType_RELU, ActivationFunctionType_RELU_N1_TO_1,
+ ActivationFunctionType_RELU6, ActivationFunctionType_TANH, ActivationFunctionType_SIGN_BIT};
+ return values;
+}
+
+inline const char *const *EnumNamesActivationFunctionType()
+{
+ static const char *const names[7] = {"NONE", "RELU", "RELU_N1_TO_1", "RELU6",
+ "TANH", "SIGN_BIT", nullptr};
+ return names;
+}
+
+inline const char *EnumNameActivationFunctionType(ActivationFunctionType e)
+{
+ if (flatbuffers::IsOutRange(e, ActivationFunctionType_NONE, ActivationFunctionType_SIGN_BIT))
+ return "";
+ const size_t index = static_cast<size_t>(e);
+ return EnumNamesActivationFunctionType()[index];
+}
+
+enum LSHProjectionType : int8_t
+{
+ LSHProjectionType_UNKNOWN = 0,
+ LSHProjectionType_SPARSE = 1,
+ LSHProjectionType_DENSE = 2,
+ LSHProjectionType_MIN = LSHProjectionType_UNKNOWN,
+ LSHProjectionType_MAX = LSHProjectionType_DENSE
+};
+
+inline const LSHProjectionType (&EnumValuesLSHProjectionType())[3]
+{
+ static const LSHProjectionType values[] = {LSHProjectionType_UNKNOWN, LSHProjectionType_SPARSE,
+ LSHProjectionType_DENSE};
+ return values;
+}
+
+inline const char *const *EnumNamesLSHProjectionType()
+{
+ static const char *const names[4] = {"UNKNOWN", "SPARSE", "DENSE", nullptr};
+ return names;
+}
+
+inline const char *EnumNameLSHProjectionType(LSHProjectionType e)
+{
+ if (flatbuffers::IsOutRange(e, LSHProjectionType_UNKNOWN, LSHProjectionType_DENSE))
+ return "";
+ const size_t index = static_cast<size_t>(e);
+ return EnumNamesLSHProjectionType()[index];
+}
+
+enum FullyConnectedOptionsWeightsFormat : int8_t
+{
+ FullyConnectedOptionsWeightsFormat_DEFAULT = 0,
+ FullyConnectedOptionsWeightsFormat_SHUFFLED4x16INT8 = 1,
+ FullyConnectedOptionsWeightsFormat_SHUFFLED16x1FLOAT32 = 127,
+ FullyConnectedOptionsWeightsFormat_MIN = FullyConnectedOptionsWeightsFormat_DEFAULT,
+ FullyConnectedOptionsWeightsFormat_MAX = FullyConnectedOptionsWeightsFormat_SHUFFLED16x1FLOAT32
+};
+
+inline const FullyConnectedOptionsWeightsFormat (&EnumValuesFullyConnectedOptionsWeightsFormat())[3]
+{
+ static const FullyConnectedOptionsWeightsFormat values[] = {
+ FullyConnectedOptionsWeightsFormat_DEFAULT, FullyConnectedOptionsWeightsFormat_SHUFFLED4x16INT8,
+ FullyConnectedOptionsWeightsFormat_SHUFFLED16x1FLOAT32};
+ return values;
+}
+
+inline const char *EnumNameFullyConnectedOptionsWeightsFormat(FullyConnectedOptionsWeightsFormat e)
+{
+ switch (e)
+ {
+ case FullyConnectedOptionsWeightsFormat_DEFAULT:
+ return "DEFAULT";
+ case FullyConnectedOptionsWeightsFormat_SHUFFLED4x16INT8:
+ return "SHUFFLED4x16INT8";
+ case FullyConnectedOptionsWeightsFormat_SHUFFLED16x1FLOAT32:
+ return "SHUFFLED16x1FLOAT32";
+ default:
+ return "";
+ }
+}
+
+enum LSTMKernelType : int8_t
+{
+ LSTMKernelType_FULL = 0,
+ LSTMKernelType_BASIC = 1,
+ LSTMKernelType_MIN = LSTMKernelType_FULL,
+ LSTMKernelType_MAX = LSTMKernelType_BASIC
+};
+
+inline const LSTMKernelType (&EnumValuesLSTMKernelType())[2]
+{
+ static const LSTMKernelType values[] = {LSTMKernelType_FULL, LSTMKernelType_BASIC};
+ return values;
+}
+
+inline const char *const *EnumNamesLSTMKernelType()
+{
+ static const char *const names[3] = {"FULL", "BASIC", nullptr};
+ return names;
+}
+
+inline const char *EnumNameLSTMKernelType(LSTMKernelType e)
+{
+ if (flatbuffers::IsOutRange(e, LSTMKernelType_FULL, LSTMKernelType_BASIC))
+ return "";
+ const size_t index = static_cast<size_t>(e);
+ return EnumNamesLSTMKernelType()[index];
+}
+
+enum CombinerType : int8_t
+{
+ CombinerType_SUM = 0,
+ CombinerType_MEAN = 1,
+ CombinerType_SQRTN = 2,
+ CombinerType_MIN = CombinerType_SUM,
+ CombinerType_MAX = CombinerType_SQRTN
+};
+
+inline const CombinerType (&EnumValuesCombinerType())[3]
+{
+ static const CombinerType values[] = {CombinerType_SUM, CombinerType_MEAN, CombinerType_SQRTN};
+ return values;
+}
+
+inline const char *const *EnumNamesCombinerType()
+{
+ static const char *const names[4] = {"SUM", "MEAN", "SQRTN", nullptr};
+ return names;
+}
+
+inline const char *EnumNameCombinerType(CombinerType e)
+{
+ if (flatbuffers::IsOutRange(e, CombinerType_SUM, CombinerType_SQRTN))
+ return "";
+ const size_t index = static_cast<size_t>(e);
+ return EnumNamesCombinerType()[index];
+}
+
+enum MirrorPadMode : int8_t
+{
+ MirrorPadMode_REFLECT = 0,
+ MirrorPadMode_SYMMETRIC = 1,
+ MirrorPadMode_MIN = MirrorPadMode_REFLECT,
+ MirrorPadMode_MAX = MirrorPadMode_SYMMETRIC
+};
+
+inline const MirrorPadMode (&EnumValuesMirrorPadMode())[2]
+{
+ static const MirrorPadMode values[] = {MirrorPadMode_REFLECT, MirrorPadMode_SYMMETRIC};
+ return values;
+}
+
+inline const char *const *EnumNamesMirrorPadMode()
+{
+ static const char *const names[3] = {"REFLECT", "SYMMETRIC", nullptr};
+ return names;
+}
+
+inline const char *EnumNameMirrorPadMode(MirrorPadMode e)
+{
+ if (flatbuffers::IsOutRange(e, MirrorPadMode_REFLECT, MirrorPadMode_SYMMETRIC))
+ return "";
+ const size_t index = static_cast<size_t>(e);
+ return EnumNamesMirrorPadMode()[index];
+}
+
+enum CustomOptionsFormat : int8_t
+{
+ CustomOptionsFormat_FLEXBUFFERS = 0,
+ CustomOptionsFormat_MIN = CustomOptionsFormat_FLEXBUFFERS,
+ CustomOptionsFormat_MAX = CustomOptionsFormat_FLEXBUFFERS
+};
+
+inline const CustomOptionsFormat (&EnumValuesCustomOptionsFormat())[1]
+{
+ static const CustomOptionsFormat values[] = {CustomOptionsFormat_FLEXBUFFERS};
+ return values;
+}
+
+inline const char *const *EnumNamesCustomOptionsFormat()
+{
+ static const char *const names[2] = {"FLEXBUFFERS", nullptr};
+ return names;
+}
+
+inline const char *EnumNameCustomOptionsFormat(CustomOptionsFormat e)
+{
+ if (flatbuffers::IsOutRange(e, CustomOptionsFormat_FLEXBUFFERS, CustomOptionsFormat_FLEXBUFFERS))
+ return "";
+ const size_t index = static_cast<size_t>(e);
+ return EnumNamesCustomOptionsFormat()[index];
+}
+
+enum DataFormat : int8_t
+{
+ DataFormat_CHANNELS_LAST = 0,
+ DataFormat_CHANNELS_FIRST = 1,
+ DataFormat_MIN = DataFormat_CHANNELS_LAST,
+ DataFormat_MAX = DataFormat_CHANNELS_FIRST
+};
+
+inline const DataFormat (&EnumValuesDataFormat())[2]
+{
+ static const DataFormat values[] = {DataFormat_CHANNELS_LAST, DataFormat_CHANNELS_FIRST};
+ return values;
+}
+
+inline const char *const *EnumNamesDataFormat()
+{
+ static const char *const names[3] = {"CHANNELS_LAST", "CHANNELS_FIRST", nullptr};
+ return names;
+}
+
+inline const char *EnumNameDataFormat(DataFormat e)
+{
+ if (flatbuffers::IsOutRange(e, DataFormat_CHANNELS_LAST, DataFormat_CHANNELS_FIRST))
+ return "";
+ const size_t index = static_cast<size_t>(e);
+ return EnumNamesDataFormat()[index];
+}
+
+struct CustomQuantizationT : public flatbuffers::NativeTable
+{
+ typedef CustomQuantization TableType;
+ std::vector<uint8_t> custom{};
+};
+
+struct CustomQuantization FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef CustomQuantizationT NativeTableType;
+ typedef CustomQuantizationBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_CUSTOM = 4
+ };
+ const flatbuffers::Vector<uint8_t> *custom() const
+ {
+ return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_CUSTOM);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_CUSTOM) &&
+ verifier.VerifyVector(custom()) && verifier.EndTable();
+ }
+ CustomQuantizationT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(CustomQuantizationT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<CustomQuantization>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const CustomQuantizationT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct CustomQuantizationBuilder
+{
+ typedef CustomQuantization Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_custom(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> custom)
+ {
+ fbb_.AddOffset(CustomQuantization::VT_CUSTOM, custom);
+ }
+ explicit CustomQuantizationBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<CustomQuantization> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<CustomQuantization>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<CustomQuantization>
+CreateCustomQuantization(flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::Vector<uint8_t>> custom = 0)
+{
+ CustomQuantizationBuilder builder_(_fbb);
+ builder_.add_custom(custom);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<CustomQuantization>
+CreateCustomQuantizationDirect(flatbuffers::FlatBufferBuilder &_fbb,
+ const std::vector<uint8_t> *custom = nullptr)
+{
+ if (custom)
+ {
+ _fbb.ForceVectorAlignment(custom->size(), sizeof(uint8_t), 16);
+ }
+ auto custom__ = custom ? _fbb.CreateVector<uint8_t>(*custom) : 0;
+ return circle::CreateCustomQuantization(_fbb, custom__);
+}
+
+flatbuffers::Offset<CustomQuantization>
+CreateCustomQuantization(flatbuffers::FlatBufferBuilder &_fbb, const CustomQuantizationT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct QuantizationParametersT : public flatbuffers::NativeTable
+{
+ typedef QuantizationParameters TableType;
+ std::vector<float> min{};
+ std::vector<float> max{};
+ std::vector<float> scale{};
+ std::vector<int64_t> zero_point{};
+ circle::QuantizationDetailsUnion details{};
+ int32_t quantized_dimension = 0;
+};
+
+struct QuantizationParameters FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef QuantizationParametersT NativeTableType;
+ typedef QuantizationParametersBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_MIN = 4,
+ VT_MAX = 6,
+ VT_SCALE = 8,
+ VT_ZERO_POINT = 10,
+ VT_DETAILS_TYPE = 12,
+ VT_DETAILS = 14,
+ VT_QUANTIZED_DIMENSION = 16
+ };
+ const flatbuffers::Vector<float> *min() const
+ {
+ return GetPointer<const flatbuffers::Vector<float> *>(VT_MIN);
+ }
+ const flatbuffers::Vector<float> *max() const
+ {
+ return GetPointer<const flatbuffers::Vector<float> *>(VT_MAX);
+ }
+ const flatbuffers::Vector<float> *scale() const
+ {
+ return GetPointer<const flatbuffers::Vector<float> *>(VT_SCALE);
+ }
+ const flatbuffers::Vector<int64_t> *zero_point() const
+ {
+ return GetPointer<const flatbuffers::Vector<int64_t> *>(VT_ZERO_POINT);
+ }
+ circle::QuantizationDetails details_type() const
+ {
+ return static_cast<circle::QuantizationDetails>(GetField<uint8_t>(VT_DETAILS_TYPE, 0));
+ }
+ const void *details() const { return GetPointer<const void *>(VT_DETAILS); }
+ template <typename T> const T *details_as() const;
+ const circle::CustomQuantization *details_as_CustomQuantization() const
+ {
+ return details_type() == circle::QuantizationDetails_CustomQuantization
+ ? static_cast<const circle::CustomQuantization *>(details())
+ : nullptr;
+ }
+ int32_t quantized_dimension() const { return GetField<int32_t>(VT_QUANTIZED_DIMENSION, 0); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_MIN) &&
+ verifier.VerifyVector(min()) && VerifyOffset(verifier, VT_MAX) &&
+ verifier.VerifyVector(max()) && VerifyOffset(verifier, VT_SCALE) &&
+ verifier.VerifyVector(scale()) && VerifyOffset(verifier, VT_ZERO_POINT) &&
+ verifier.VerifyVector(zero_point()) && VerifyField<uint8_t>(verifier, VT_DETAILS_TYPE) &&
+ VerifyOffset(verifier, VT_DETAILS) &&
+ VerifyQuantizationDetails(verifier, details(), details_type()) &&
+ VerifyField<int32_t>(verifier, VT_QUANTIZED_DIMENSION) && verifier.EndTable();
+ }
+ QuantizationParametersT *
+ UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(QuantizationParametersT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<QuantizationParameters>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const QuantizationParametersT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+template <>
+inline const circle::CustomQuantization *
+QuantizationParameters::details_as<circle::CustomQuantization>() const
+{
+ return details_as_CustomQuantization();
+}
+
+struct QuantizationParametersBuilder
+{
+ typedef QuantizationParameters Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_min(flatbuffers::Offset<flatbuffers::Vector<float>> min)
+ {
+ fbb_.AddOffset(QuantizationParameters::VT_MIN, min);
+ }
+ void add_max(flatbuffers::Offset<flatbuffers::Vector<float>> max)
+ {
+ fbb_.AddOffset(QuantizationParameters::VT_MAX, max);
+ }
+ void add_scale(flatbuffers::Offset<flatbuffers::Vector<float>> scale)
+ {
+ fbb_.AddOffset(QuantizationParameters::VT_SCALE, scale);
+ }
+ void add_zero_point(flatbuffers::Offset<flatbuffers::Vector<int64_t>> zero_point)
+ {
+ fbb_.AddOffset(QuantizationParameters::VT_ZERO_POINT, zero_point);
+ }
+ void add_details_type(circle::QuantizationDetails details_type)
+ {
+ fbb_.AddElement<uint8_t>(QuantizationParameters::VT_DETAILS_TYPE,
+ static_cast<uint8_t>(details_type), 0);
+ }
+ void add_details(flatbuffers::Offset<void> details)
+ {
+ fbb_.AddOffset(QuantizationParameters::VT_DETAILS, details);
+ }
+ void add_quantized_dimension(int32_t quantized_dimension)
+ {
+ fbb_.AddElement<int32_t>(QuantizationParameters::VT_QUANTIZED_DIMENSION, quantized_dimension,
+ 0);
+ }
+ explicit QuantizationParametersBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<QuantizationParameters> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<QuantizationParameters>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<QuantizationParameters> CreateQuantizationParameters(
+ flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::Offset<flatbuffers::Vector<float>> min = 0,
+ flatbuffers::Offset<flatbuffers::Vector<float>> max = 0,
+ flatbuffers::Offset<flatbuffers::Vector<float>> scale = 0,
+ flatbuffers::Offset<flatbuffers::Vector<int64_t>> zero_point = 0,
+ circle::QuantizationDetails details_type = circle::QuantizationDetails_NONE,
+ flatbuffers::Offset<void> details = 0, int32_t quantized_dimension = 0)
+{
+ QuantizationParametersBuilder builder_(_fbb);
+ builder_.add_quantized_dimension(quantized_dimension);
+ builder_.add_details(details);
+ builder_.add_zero_point(zero_point);
+ builder_.add_scale(scale);
+ builder_.add_max(max);
+ builder_.add_min(min);
+ builder_.add_details_type(details_type);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<QuantizationParameters> CreateQuantizationParametersDirect(
+ flatbuffers::FlatBufferBuilder &_fbb, const std::vector<float> *min = nullptr,
+ const std::vector<float> *max = nullptr, const std::vector<float> *scale = nullptr,
+ const std::vector<int64_t> *zero_point = nullptr,
+ circle::QuantizationDetails details_type = circle::QuantizationDetails_NONE,
+ flatbuffers::Offset<void> details = 0, int32_t quantized_dimension = 0)
+{
+ auto min__ = min ? _fbb.CreateVector<float>(*min) : 0;
+ auto max__ = max ? _fbb.CreateVector<float>(*max) : 0;
+ auto scale__ = scale ? _fbb.CreateVector<float>(*scale) : 0;
+ auto zero_point__ = zero_point ? _fbb.CreateVector<int64_t>(*zero_point) : 0;
+ return circle::CreateQuantizationParameters(_fbb, min__, max__, scale__, zero_point__,
+ details_type, details, quantized_dimension);
+}
+
+flatbuffers::Offset<QuantizationParameters>
+CreateQuantizationParameters(flatbuffers::FlatBufferBuilder &_fbb,
+ const QuantizationParametersT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct Int32VectorT : public flatbuffers::NativeTable
+{
+ typedef Int32Vector TableType;
+ std::vector<int32_t> values{};
+};
+
+struct Int32Vector FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef Int32VectorT NativeTableType;
+ typedef Int32VectorBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_VALUES = 4
+ };
+ const flatbuffers::Vector<int32_t> *values() const
+ {
+ return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_VALUES);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_VALUES) &&
+ verifier.VerifyVector(values()) && verifier.EndTable();
+ }
+ Int32VectorT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(Int32VectorT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<Int32Vector>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const Int32VectorT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct Int32VectorBuilder
+{
+ typedef Int32Vector Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_values(flatbuffers::Offset<flatbuffers::Vector<int32_t>> values)
+ {
+ fbb_.AddOffset(Int32Vector::VT_VALUES, values);
+ }
+ explicit Int32VectorBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<Int32Vector> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Int32Vector>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Int32Vector>
+CreateInt32Vector(flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::Vector<int32_t>> values = 0)
+{
+ Int32VectorBuilder builder_(_fbb);
+ builder_.add_values(values);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<Int32Vector>
+CreateInt32VectorDirect(flatbuffers::FlatBufferBuilder &_fbb,
+ const std::vector<int32_t> *values = nullptr)
+{
+ auto values__ = values ? _fbb.CreateVector<int32_t>(*values) : 0;
+ return circle::CreateInt32Vector(_fbb, values__);
+}
+
+flatbuffers::Offset<Int32Vector>
+CreateInt32Vector(flatbuffers::FlatBufferBuilder &_fbb, const Int32VectorT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct Uint16VectorT : public flatbuffers::NativeTable
+{
+ typedef Uint16Vector TableType;
+ std::vector<uint16_t> values{};
+};
+
+struct Uint16Vector FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef Uint16VectorT NativeTableType;
+ typedef Uint16VectorBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_VALUES = 4
+ };
+ const flatbuffers::Vector<uint16_t> *values() const
+ {
+ return GetPointer<const flatbuffers::Vector<uint16_t> *>(VT_VALUES);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_VALUES) &&
+ verifier.VerifyVector(values()) && verifier.EndTable();
+ }
+ Uint16VectorT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(Uint16VectorT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<Uint16Vector>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const Uint16VectorT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct Uint16VectorBuilder
+{
+ typedef Uint16Vector Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_values(flatbuffers::Offset<flatbuffers::Vector<uint16_t>> values)
+ {
+ fbb_.AddOffset(Uint16Vector::VT_VALUES, values);
+ }
+ explicit Uint16VectorBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<Uint16Vector> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Uint16Vector>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Uint16Vector>
+CreateUint16Vector(flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::Vector<uint16_t>> values = 0)
+{
+ Uint16VectorBuilder builder_(_fbb);
+ builder_.add_values(values);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<Uint16Vector>
+CreateUint16VectorDirect(flatbuffers::FlatBufferBuilder &_fbb,
+ const std::vector<uint16_t> *values = nullptr)
+{
+ if (values)
+ {
+ _fbb.ForceVectorAlignment(values->size(), sizeof(uint16_t), 4);
+ }
+ auto values__ = values ? _fbb.CreateVector<uint16_t>(*values) : 0;
+ return circle::CreateUint16Vector(_fbb, values__);
+}
+
+flatbuffers::Offset<Uint16Vector>
+CreateUint16Vector(flatbuffers::FlatBufferBuilder &_fbb, const Uint16VectorT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct Uint8VectorT : public flatbuffers::NativeTable
+{
+ typedef Uint8Vector TableType;
+ std::vector<uint8_t> values{};
+};
+
+struct Uint8Vector FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef Uint8VectorT NativeTableType;
+ typedef Uint8VectorBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_VALUES = 4
+ };
+ const flatbuffers::Vector<uint8_t> *values() const
+ {
+ return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_VALUES);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_VALUES) &&
+ verifier.VerifyVector(values()) && verifier.EndTable();
+ }
+ Uint8VectorT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(Uint8VectorT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<Uint8Vector>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const Uint8VectorT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct Uint8VectorBuilder
+{
+ typedef Uint8Vector Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_values(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> values)
+ {
+ fbb_.AddOffset(Uint8Vector::VT_VALUES, values);
+ }
+ explicit Uint8VectorBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<Uint8Vector> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Uint8Vector>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Uint8Vector>
+CreateUint8Vector(flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::Vector<uint8_t>> values = 0)
+{
+ Uint8VectorBuilder builder_(_fbb);
+ builder_.add_values(values);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<Uint8Vector>
+CreateUint8VectorDirect(flatbuffers::FlatBufferBuilder &_fbb,
+ const std::vector<uint8_t> *values = nullptr)
+{
+ if (values)
+ {
+ _fbb.ForceVectorAlignment(values->size(), sizeof(uint8_t), 4);
+ }
+ auto values__ = values ? _fbb.CreateVector<uint8_t>(*values) : 0;
+ return circle::CreateUint8Vector(_fbb, values__);
+}
+
+flatbuffers::Offset<Uint8Vector>
+CreateUint8Vector(flatbuffers::FlatBufferBuilder &_fbb, const Uint8VectorT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct DimensionMetadataT : public flatbuffers::NativeTable
+{
+ typedef DimensionMetadata TableType;
+ circle::DimensionType format = circle::DimensionType_DENSE;
+ int32_t dense_size = 0;
+ circle::SparseIndexVectorUnion array_segments{};
+ circle::SparseIndexVectorUnion array_indices{};
+};
+
+struct DimensionMetadata FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef DimensionMetadataT NativeTableType;
+ typedef DimensionMetadataBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_FORMAT = 4,
+ VT_DENSE_SIZE = 6,
+ VT_ARRAY_SEGMENTS_TYPE = 8,
+ VT_ARRAY_SEGMENTS = 10,
+ VT_ARRAY_INDICES_TYPE = 12,
+ VT_ARRAY_INDICES = 14
+ };
+ circle::DimensionType format() const
+ {
+ return static_cast<circle::DimensionType>(GetField<int8_t>(VT_FORMAT, 0));
+ }
+ int32_t dense_size() const { return GetField<int32_t>(VT_DENSE_SIZE, 0); }
+ circle::SparseIndexVector array_segments_type() const
+ {
+ return static_cast<circle::SparseIndexVector>(GetField<uint8_t>(VT_ARRAY_SEGMENTS_TYPE, 0));
+ }
+ const void *array_segments() const { return GetPointer<const void *>(VT_ARRAY_SEGMENTS); }
+ template <typename T> const T *array_segments_as() const;
+ const circle::Int32Vector *array_segments_as_Int32Vector() const
+ {
+ return array_segments_type() == circle::SparseIndexVector_Int32Vector
+ ? static_cast<const circle::Int32Vector *>(array_segments())
+ : nullptr;
+ }
+ const circle::Uint16Vector *array_segments_as_Uint16Vector() const
+ {
+ return array_segments_type() == circle::SparseIndexVector_Uint16Vector
+ ? static_cast<const circle::Uint16Vector *>(array_segments())
+ : nullptr;
+ }
+ const circle::Uint8Vector *array_segments_as_Uint8Vector() const
+ {
+ return array_segments_type() == circle::SparseIndexVector_Uint8Vector
+ ? static_cast<const circle::Uint8Vector *>(array_segments())
+ : nullptr;
+ }
+ circle::SparseIndexVector array_indices_type() const
+ {
+ return static_cast<circle::SparseIndexVector>(GetField<uint8_t>(VT_ARRAY_INDICES_TYPE, 0));
+ }
+ const void *array_indices() const { return GetPointer<const void *>(VT_ARRAY_INDICES); }
+ template <typename T> const T *array_indices_as() const;
+ const circle::Int32Vector *array_indices_as_Int32Vector() const
+ {
+ return array_indices_type() == circle::SparseIndexVector_Int32Vector
+ ? static_cast<const circle::Int32Vector *>(array_indices())
+ : nullptr;
+ }
+ const circle::Uint16Vector *array_indices_as_Uint16Vector() const
+ {
+ return array_indices_type() == circle::SparseIndexVector_Uint16Vector
+ ? static_cast<const circle::Uint16Vector *>(array_indices())
+ : nullptr;
+ }
+ const circle::Uint8Vector *array_indices_as_Uint8Vector() const
+ {
+ return array_indices_type() == circle::SparseIndexVector_Uint8Vector
+ ? static_cast<const circle::Uint8Vector *>(array_indices())
+ : nullptr;
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_FORMAT) &&
+ VerifyField<int32_t>(verifier, VT_DENSE_SIZE) &&
+ VerifyField<uint8_t>(verifier, VT_ARRAY_SEGMENTS_TYPE) &&
+ VerifyOffset(verifier, VT_ARRAY_SEGMENTS) &&
+ VerifySparseIndexVector(verifier, array_segments(), array_segments_type()) &&
+ VerifyField<uint8_t>(verifier, VT_ARRAY_INDICES_TYPE) &&
+ VerifyOffset(verifier, VT_ARRAY_INDICES) &&
+ VerifySparseIndexVector(verifier, array_indices(), array_indices_type()) &&
+ verifier.EndTable();
+ }
+ DimensionMetadataT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(DimensionMetadataT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<DimensionMetadata>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const DimensionMetadataT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+template <>
+inline const circle::Int32Vector *DimensionMetadata::array_segments_as<circle::Int32Vector>() const
+{
+ return array_segments_as_Int32Vector();
+}
+
+template <>
+inline const circle::Uint16Vector *
+DimensionMetadata::array_segments_as<circle::Uint16Vector>() const
+{
+ return array_segments_as_Uint16Vector();
+}
+
+template <>
+inline const circle::Uint8Vector *DimensionMetadata::array_segments_as<circle::Uint8Vector>() const
+{
+ return array_segments_as_Uint8Vector();
+}
+
+template <>
+inline const circle::Int32Vector *DimensionMetadata::array_indices_as<circle::Int32Vector>() const
+{
+ return array_indices_as_Int32Vector();
+}
+
+template <>
+inline const circle::Uint16Vector *DimensionMetadata::array_indices_as<circle::Uint16Vector>() const
+{
+ return array_indices_as_Uint16Vector();
+}
+
+template <>
+inline const circle::Uint8Vector *DimensionMetadata::array_indices_as<circle::Uint8Vector>() const
+{
+ return array_indices_as_Uint8Vector();
+}
+
+struct DimensionMetadataBuilder
+{
+ typedef DimensionMetadata Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_format(circle::DimensionType format)
+ {
+ fbb_.AddElement<int8_t>(DimensionMetadata::VT_FORMAT, static_cast<int8_t>(format), 0);
+ }
+ void add_dense_size(int32_t dense_size)
+ {
+ fbb_.AddElement<int32_t>(DimensionMetadata::VT_DENSE_SIZE, dense_size, 0);
+ }
+ void add_array_segments_type(circle::SparseIndexVector array_segments_type)
+ {
+ fbb_.AddElement<uint8_t>(DimensionMetadata::VT_ARRAY_SEGMENTS_TYPE,
+ static_cast<uint8_t>(array_segments_type), 0);
+ }
+ void add_array_segments(flatbuffers::Offset<void> array_segments)
+ {
+ fbb_.AddOffset(DimensionMetadata::VT_ARRAY_SEGMENTS, array_segments);
+ }
+ void add_array_indices_type(circle::SparseIndexVector array_indices_type)
+ {
+ fbb_.AddElement<uint8_t>(DimensionMetadata::VT_ARRAY_INDICES_TYPE,
+ static_cast<uint8_t>(array_indices_type), 0);
+ }
+ void add_array_indices(flatbuffers::Offset<void> array_indices)
+ {
+ fbb_.AddOffset(DimensionMetadata::VT_ARRAY_INDICES, array_indices);
+ }
+ explicit DimensionMetadataBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<DimensionMetadata> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<DimensionMetadata>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<DimensionMetadata> CreateDimensionMetadata(
+ flatbuffers::FlatBufferBuilder &_fbb, circle::DimensionType format = circle::DimensionType_DENSE,
+ int32_t dense_size = 0,
+ circle::SparseIndexVector array_segments_type = circle::SparseIndexVector_NONE,
+ flatbuffers::Offset<void> array_segments = 0,
+ circle::SparseIndexVector array_indices_type = circle::SparseIndexVector_NONE,
+ flatbuffers::Offset<void> array_indices = 0)
+{
+ DimensionMetadataBuilder builder_(_fbb);
+ builder_.add_array_indices(array_indices);
+ builder_.add_array_segments(array_segments);
+ builder_.add_dense_size(dense_size);
+ builder_.add_array_indices_type(array_indices_type);
+ builder_.add_array_segments_type(array_segments_type);
+ builder_.add_format(format);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<DimensionMetadata>
+CreateDimensionMetadata(flatbuffers::FlatBufferBuilder &_fbb, const DimensionMetadataT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct SparsityParametersT : public flatbuffers::NativeTable
+{
+ typedef SparsityParameters TableType;
+ std::vector<int32_t> traversal_order{};
+ std::vector<int32_t> block_map{};
+ std::vector<std::unique_ptr<circle::DimensionMetadataT>> dim_metadata{};
+};
+
+struct SparsityParameters FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef SparsityParametersT NativeTableType;
+ typedef SparsityParametersBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_TRAVERSAL_ORDER = 4,
+ VT_BLOCK_MAP = 6,
+ VT_DIM_METADATA = 8
+ };
+ const flatbuffers::Vector<int32_t> *traversal_order() const
+ {
+ return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_TRAVERSAL_ORDER);
+ }
+ const flatbuffers::Vector<int32_t> *block_map() const
+ {
+ return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_BLOCK_MAP);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<circle::DimensionMetadata>> *dim_metadata() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<circle::DimensionMetadata>> *>(
+ VT_DIM_METADATA);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_TRAVERSAL_ORDER) &&
+ verifier.VerifyVector(traversal_order()) && VerifyOffset(verifier, VT_BLOCK_MAP) &&
+ verifier.VerifyVector(block_map()) && VerifyOffset(verifier, VT_DIM_METADATA) &&
+ verifier.VerifyVector(dim_metadata()) && verifier.VerifyVectorOfTables(dim_metadata()) &&
+ verifier.EndTable();
+ }
+ SparsityParametersT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(SparsityParametersT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<SparsityParameters>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const SparsityParametersT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct SparsityParametersBuilder
+{
+ typedef SparsityParameters Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_traversal_order(flatbuffers::Offset<flatbuffers::Vector<int32_t>> traversal_order)
+ {
+ fbb_.AddOffset(SparsityParameters::VT_TRAVERSAL_ORDER, traversal_order);
+ }
+ void add_block_map(flatbuffers::Offset<flatbuffers::Vector<int32_t>> block_map)
+ {
+ fbb_.AddOffset(SparsityParameters::VT_BLOCK_MAP, block_map);
+ }
+ void add_dim_metadata(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::DimensionMetadata>>>
+ dim_metadata)
+ {
+ fbb_.AddOffset(SparsityParameters::VT_DIM_METADATA, dim_metadata);
+ }
+ explicit SparsityParametersBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<SparsityParameters> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<SparsityParameters>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<SparsityParameters> CreateSparsityParameters(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::Vector<int32_t>> traversal_order = 0,
+ flatbuffers::Offset<flatbuffers::Vector<int32_t>> block_map = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::DimensionMetadata>>>
+ dim_metadata = 0)
+{
+ SparsityParametersBuilder builder_(_fbb);
+ builder_.add_dim_metadata(dim_metadata);
+ builder_.add_block_map(block_map);
+ builder_.add_traversal_order(traversal_order);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<SparsityParameters> CreateSparsityParametersDirect(
+ flatbuffers::FlatBufferBuilder &_fbb, const std::vector<int32_t> *traversal_order = nullptr,
+ const std::vector<int32_t> *block_map = nullptr,
+ const std::vector<flatbuffers::Offset<circle::DimensionMetadata>> *dim_metadata = nullptr)
+{
+ auto traversal_order__ = traversal_order ? _fbb.CreateVector<int32_t>(*traversal_order) : 0;
+ auto block_map__ = block_map ? _fbb.CreateVector<int32_t>(*block_map) : 0;
+ auto dim_metadata__ =
+ dim_metadata ? _fbb.CreateVector<flatbuffers::Offset<circle::DimensionMetadata>>(*dim_metadata)
+ : 0;
+ return circle::CreateSparsityParameters(_fbb, traversal_order__, block_map__, dim_metadata__);
+}
+
+flatbuffers::Offset<SparsityParameters>
+CreateSparsityParameters(flatbuffers::FlatBufferBuilder &_fbb, const SparsityParametersT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct TensorT : public flatbuffers::NativeTable
+{
+ typedef Tensor TableType;
+ std::vector<int32_t> shape{};
+ circle::TensorType type = circle::TensorType_FLOAT32;
+ uint32_t buffer = 0;
+ std::string name{};
+ std::unique_ptr<circle::QuantizationParametersT> quantization{};
+ bool is_variable = false;
+ std::unique_ptr<circle::SparsityParametersT> sparsity{};
+ std::vector<int32_t> shape_signature{};
+};
+
+struct Tensor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef TensorT NativeTableType;
+ typedef TensorBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_SHAPE = 4,
+ VT_TYPE = 6,
+ VT_BUFFER = 8,
+ VT_NAME = 10,
+ VT_QUANTIZATION = 12,
+ VT_IS_VARIABLE = 14,
+ VT_SPARSITY = 16,
+ VT_SHAPE_SIGNATURE = 18
+ };
+ const flatbuffers::Vector<int32_t> *shape() const
+ {
+ return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_SHAPE);
+ }
+ circle::TensorType type() const
+ {
+ return static_cast<circle::TensorType>(GetField<int8_t>(VT_TYPE, 0));
+ }
+ uint32_t buffer() const { return GetField<uint32_t>(VT_BUFFER, 0); }
+ const flatbuffers::String *name() const
+ {
+ return GetPointer<const flatbuffers::String *>(VT_NAME);
+ }
+ const circle::QuantizationParameters *quantization() const
+ {
+ return GetPointer<const circle::QuantizationParameters *>(VT_QUANTIZATION);
+ }
+ bool is_variable() const { return GetField<uint8_t>(VT_IS_VARIABLE, 0) != 0; }
+ const circle::SparsityParameters *sparsity() const
+ {
+ return GetPointer<const circle::SparsityParameters *>(VT_SPARSITY);
+ }
+ const flatbuffers::Vector<int32_t> *shape_signature() const
+ {
+ return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_SHAPE_SIGNATURE);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_SHAPE) &&
+ verifier.VerifyVector(shape()) && VerifyField<int8_t>(verifier, VT_TYPE) &&
+ VerifyField<uint32_t>(verifier, VT_BUFFER) && VerifyOffset(verifier, VT_NAME) &&
+ verifier.VerifyString(name()) && VerifyOffset(verifier, VT_QUANTIZATION) &&
+ verifier.VerifyTable(quantization()) && VerifyField<uint8_t>(verifier, VT_IS_VARIABLE) &&
+ VerifyOffset(verifier, VT_SPARSITY) && verifier.VerifyTable(sparsity()) &&
+ VerifyOffset(verifier, VT_SHAPE_SIGNATURE) && verifier.VerifyVector(shape_signature()) &&
+ verifier.EndTable();
+ }
+ TensorT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(TensorT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<Tensor>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const TensorT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct TensorBuilder
+{
+ typedef Tensor Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_shape(flatbuffers::Offset<flatbuffers::Vector<int32_t>> shape)
+ {
+ fbb_.AddOffset(Tensor::VT_SHAPE, shape);
+ }
+ void add_type(circle::TensorType type)
+ {
+ fbb_.AddElement<int8_t>(Tensor::VT_TYPE, static_cast<int8_t>(type), 0);
+ }
+ void add_buffer(uint32_t buffer) { fbb_.AddElement<uint32_t>(Tensor::VT_BUFFER, buffer, 0); }
+ void add_name(flatbuffers::Offset<flatbuffers::String> name)
+ {
+ fbb_.AddOffset(Tensor::VT_NAME, name);
+ }
+ void add_quantization(flatbuffers::Offset<circle::QuantizationParameters> quantization)
+ {
+ fbb_.AddOffset(Tensor::VT_QUANTIZATION, quantization);
+ }
+ void add_is_variable(bool is_variable)
+ {
+ fbb_.AddElement<uint8_t>(Tensor::VT_IS_VARIABLE, static_cast<uint8_t>(is_variable), 0);
+ }
+ void add_sparsity(flatbuffers::Offset<circle::SparsityParameters> sparsity)
+ {
+ fbb_.AddOffset(Tensor::VT_SPARSITY, sparsity);
+ }
+ void add_shape_signature(flatbuffers::Offset<flatbuffers::Vector<int32_t>> shape_signature)
+ {
+ fbb_.AddOffset(Tensor::VT_SHAPE_SIGNATURE, shape_signature);
+ }
+ explicit TensorBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<Tensor> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Tensor>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Tensor>
+CreateTensor(flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::Vector<int32_t>> shape = 0,
+ circle::TensorType type = circle::TensorType_FLOAT32, uint32_t buffer = 0,
+ flatbuffers::Offset<flatbuffers::String> name = 0,
+ flatbuffers::Offset<circle::QuantizationParameters> quantization = 0,
+ bool is_variable = false, flatbuffers::Offset<circle::SparsityParameters> sparsity = 0,
+ flatbuffers::Offset<flatbuffers::Vector<int32_t>> shape_signature = 0)
+{
+ TensorBuilder builder_(_fbb);
+ builder_.add_shape_signature(shape_signature);
+ builder_.add_sparsity(sparsity);
+ builder_.add_quantization(quantization);
+ builder_.add_name(name);
+ builder_.add_buffer(buffer);
+ builder_.add_shape(shape);
+ builder_.add_is_variable(is_variable);
+ builder_.add_type(type);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<Tensor> CreateTensorDirect(
+ flatbuffers::FlatBufferBuilder &_fbb, const std::vector<int32_t> *shape = nullptr,
+ circle::TensorType type = circle::TensorType_FLOAT32, uint32_t buffer = 0,
+ const char *name = nullptr, flatbuffers::Offset<circle::QuantizationParameters> quantization = 0,
+ bool is_variable = false, flatbuffers::Offset<circle::SparsityParameters> sparsity = 0,
+ const std::vector<int32_t> *shape_signature = nullptr)
+{
+ auto shape__ = shape ? _fbb.CreateVector<int32_t>(*shape) : 0;
+ auto name__ = name ? _fbb.CreateString(name) : 0;
+ auto shape_signature__ = shape_signature ? _fbb.CreateVector<int32_t>(*shape_signature) : 0;
+ return circle::CreateTensor(_fbb, shape__, type, buffer, name__, quantization, is_variable,
+ sparsity, shape_signature__);
+}
+
+flatbuffers::Offset<Tensor>
+CreateTensor(flatbuffers::FlatBufferBuilder &_fbb, const TensorT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct Conv2DOptionsT : public flatbuffers::NativeTable
+{
+ typedef Conv2DOptions TableType;
+ circle::Padding padding = circle::Padding_SAME;
+ int32_t stride_w = 0;
+ int32_t stride_h = 0;
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
+ int32_t dilation_w_factor = 1;
+ int32_t dilation_h_factor = 1;
+};
+
+struct Conv2DOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef Conv2DOptionsT NativeTableType;
+ typedef Conv2DOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_PADDING = 4,
+ VT_STRIDE_W = 6,
+ VT_STRIDE_H = 8,
+ VT_FUSED_ACTIVATION_FUNCTION = 10,
+ VT_DILATION_W_FACTOR = 12,
+ VT_DILATION_H_FACTOR = 14
+ };
+ circle::Padding padding() const
+ {
+ return static_cast<circle::Padding>(GetField<int8_t>(VT_PADDING, 0));
+ }
+ int32_t stride_w() const { return GetField<int32_t>(VT_STRIDE_W, 0); }
+ int32_t stride_h() const { return GetField<int32_t>(VT_STRIDE_H, 0); }
+ circle::ActivationFunctionType fused_activation_function() const
+ {
+ return static_cast<circle::ActivationFunctionType>(
+ GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+ }
+ int32_t dilation_w_factor() const { return GetField<int32_t>(VT_DILATION_W_FACTOR, 1); }
+ int32_t dilation_h_factor() const { return GetField<int32_t>(VT_DILATION_H_FACTOR, 1); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_PADDING) &&
+ VerifyField<int32_t>(verifier, VT_STRIDE_W) &&
+ VerifyField<int32_t>(verifier, VT_STRIDE_H) &&
+ VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION) &&
+ VerifyField<int32_t>(verifier, VT_DILATION_W_FACTOR) &&
+ VerifyField<int32_t>(verifier, VT_DILATION_H_FACTOR) && verifier.EndTable();
+ }
+ Conv2DOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(Conv2DOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<Conv2DOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const Conv2DOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct Conv2DOptionsBuilder
+{
+ typedef Conv2DOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_padding(circle::Padding padding)
+ {
+ fbb_.AddElement<int8_t>(Conv2DOptions::VT_PADDING, static_cast<int8_t>(padding), 0);
+ }
+ void add_stride_w(int32_t stride_w)
+ {
+ fbb_.AddElement<int32_t>(Conv2DOptions::VT_STRIDE_W, stride_w, 0);
+ }
+ void add_stride_h(int32_t stride_h)
+ {
+ fbb_.AddElement<int32_t>(Conv2DOptions::VT_STRIDE_H, stride_h, 0);
+ }
+ void add_fused_activation_function(circle::ActivationFunctionType fused_activation_function)
+ {
+ fbb_.AddElement<int8_t>(Conv2DOptions::VT_FUSED_ACTIVATION_FUNCTION,
+ static_cast<int8_t>(fused_activation_function), 0);
+ }
+ void add_dilation_w_factor(int32_t dilation_w_factor)
+ {
+ fbb_.AddElement<int32_t>(Conv2DOptions::VT_DILATION_W_FACTOR, dilation_w_factor, 1);
+ }
+ void add_dilation_h_factor(int32_t dilation_h_factor)
+ {
+ fbb_.AddElement<int32_t>(Conv2DOptions::VT_DILATION_H_FACTOR, dilation_h_factor, 1);
+ }
+ explicit Conv2DOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<Conv2DOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Conv2DOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Conv2DOptions> CreateConv2DOptions(
+ flatbuffers::FlatBufferBuilder &_fbb, circle::Padding padding = circle::Padding_SAME,
+ int32_t stride_w = 0, int32_t stride_h = 0,
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE,
+ int32_t dilation_w_factor = 1, int32_t dilation_h_factor = 1)
+{
+ Conv2DOptionsBuilder builder_(_fbb);
+ builder_.add_dilation_h_factor(dilation_h_factor);
+ builder_.add_dilation_w_factor(dilation_w_factor);
+ builder_.add_stride_h(stride_h);
+ builder_.add_stride_w(stride_w);
+ builder_.add_fused_activation_function(fused_activation_function);
+ builder_.add_padding(padding);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<Conv2DOptions>
+CreateConv2DOptions(flatbuffers::FlatBufferBuilder &_fbb, const Conv2DOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct Conv3DOptionsT : public flatbuffers::NativeTable
+{
+ typedef Conv3DOptions TableType;
+ circle::Padding padding = circle::Padding_SAME;
+ int32_t stride_d = 0;
+ int32_t stride_w = 0;
+ int32_t stride_h = 0;
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
+ int32_t dilation_d_factor = 1;
+ int32_t dilation_w_factor = 1;
+ int32_t dilation_h_factor = 1;
+};
+
+struct Conv3DOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef Conv3DOptionsT NativeTableType;
+ typedef Conv3DOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_PADDING = 4,
+ VT_STRIDE_D = 6,
+ VT_STRIDE_W = 8,
+ VT_STRIDE_H = 10,
+ VT_FUSED_ACTIVATION_FUNCTION = 12,
+ VT_DILATION_D_FACTOR = 14,
+ VT_DILATION_W_FACTOR = 16,
+ VT_DILATION_H_FACTOR = 18
+ };
+ circle::Padding padding() const
+ {
+ return static_cast<circle::Padding>(GetField<int8_t>(VT_PADDING, 0));
+ }
+ int32_t stride_d() const { return GetField<int32_t>(VT_STRIDE_D, 0); }
+ int32_t stride_w() const { return GetField<int32_t>(VT_STRIDE_W, 0); }
+ int32_t stride_h() const { return GetField<int32_t>(VT_STRIDE_H, 0); }
+ circle::ActivationFunctionType fused_activation_function() const
+ {
+ return static_cast<circle::ActivationFunctionType>(
+ GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+ }
+ int32_t dilation_d_factor() const { return GetField<int32_t>(VT_DILATION_D_FACTOR, 1); }
+ int32_t dilation_w_factor() const { return GetField<int32_t>(VT_DILATION_W_FACTOR, 1); }
+ int32_t dilation_h_factor() const { return GetField<int32_t>(VT_DILATION_H_FACTOR, 1); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_PADDING) &&
+ VerifyField<int32_t>(verifier, VT_STRIDE_D) &&
+ VerifyField<int32_t>(verifier, VT_STRIDE_W) &&
+ VerifyField<int32_t>(verifier, VT_STRIDE_H) &&
+ VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION) &&
+ VerifyField<int32_t>(verifier, VT_DILATION_D_FACTOR) &&
+ VerifyField<int32_t>(verifier, VT_DILATION_W_FACTOR) &&
+ VerifyField<int32_t>(verifier, VT_DILATION_H_FACTOR) && verifier.EndTable();
+ }
+ Conv3DOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(Conv3DOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<Conv3DOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const Conv3DOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct Conv3DOptionsBuilder
+{
+ typedef Conv3DOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_padding(circle::Padding padding)
+ {
+ fbb_.AddElement<int8_t>(Conv3DOptions::VT_PADDING, static_cast<int8_t>(padding), 0);
+ }
+ void add_stride_d(int32_t stride_d)
+ {
+ fbb_.AddElement<int32_t>(Conv3DOptions::VT_STRIDE_D, stride_d, 0);
+ }
+ void add_stride_w(int32_t stride_w)
+ {
+ fbb_.AddElement<int32_t>(Conv3DOptions::VT_STRIDE_W, stride_w, 0);
+ }
+ void add_stride_h(int32_t stride_h)
+ {
+ fbb_.AddElement<int32_t>(Conv3DOptions::VT_STRIDE_H, stride_h, 0);
+ }
+ void add_fused_activation_function(circle::ActivationFunctionType fused_activation_function)
+ {
+ fbb_.AddElement<int8_t>(Conv3DOptions::VT_FUSED_ACTIVATION_FUNCTION,
+ static_cast<int8_t>(fused_activation_function), 0);
+ }
+ void add_dilation_d_factor(int32_t dilation_d_factor)
+ {
+ fbb_.AddElement<int32_t>(Conv3DOptions::VT_DILATION_D_FACTOR, dilation_d_factor, 1);
+ }
+ void add_dilation_w_factor(int32_t dilation_w_factor)
+ {
+ fbb_.AddElement<int32_t>(Conv3DOptions::VT_DILATION_W_FACTOR, dilation_w_factor, 1);
+ }
+ void add_dilation_h_factor(int32_t dilation_h_factor)
+ {
+ fbb_.AddElement<int32_t>(Conv3DOptions::VT_DILATION_H_FACTOR, dilation_h_factor, 1);
+ }
+ explicit Conv3DOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<Conv3DOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Conv3DOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Conv3DOptions> CreateConv3DOptions(
+ flatbuffers::FlatBufferBuilder &_fbb, circle::Padding padding = circle::Padding_SAME,
+ int32_t stride_d = 0, int32_t stride_w = 0, int32_t stride_h = 0,
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE,
+ int32_t dilation_d_factor = 1, int32_t dilation_w_factor = 1, int32_t dilation_h_factor = 1)
+{
+ Conv3DOptionsBuilder builder_(_fbb);
+ builder_.add_dilation_h_factor(dilation_h_factor);
+ builder_.add_dilation_w_factor(dilation_w_factor);
+ builder_.add_dilation_d_factor(dilation_d_factor);
+ builder_.add_stride_h(stride_h);
+ builder_.add_stride_w(stride_w);
+ builder_.add_stride_d(stride_d);
+ builder_.add_fused_activation_function(fused_activation_function);
+ builder_.add_padding(padding);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<Conv3DOptions>
+CreateConv3DOptions(flatbuffers::FlatBufferBuilder &_fbb, const Conv3DOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct Pool2DOptionsT : public flatbuffers::NativeTable
+{
+ typedef Pool2DOptions TableType;
+ circle::Padding padding = circle::Padding_SAME;
+ int32_t stride_w = 0;
+ int32_t stride_h = 0;
+ int32_t filter_width = 0;
+ int32_t filter_height = 0;
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
+};
+
+struct Pool2DOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef Pool2DOptionsT NativeTableType;
+ typedef Pool2DOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_PADDING = 4,
+ VT_STRIDE_W = 6,
+ VT_STRIDE_H = 8,
+ VT_FILTER_WIDTH = 10,
+ VT_FILTER_HEIGHT = 12,
+ VT_FUSED_ACTIVATION_FUNCTION = 14
+ };
+ circle::Padding padding() const
+ {
+ return static_cast<circle::Padding>(GetField<int8_t>(VT_PADDING, 0));
+ }
+ int32_t stride_w() const { return GetField<int32_t>(VT_STRIDE_W, 0); }
+ int32_t stride_h() const { return GetField<int32_t>(VT_STRIDE_H, 0); }
+ int32_t filter_width() const { return GetField<int32_t>(VT_FILTER_WIDTH, 0); }
+ int32_t filter_height() const { return GetField<int32_t>(VT_FILTER_HEIGHT, 0); }
+ circle::ActivationFunctionType fused_activation_function() const
+ {
+ return static_cast<circle::ActivationFunctionType>(
+ GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_PADDING) &&
+ VerifyField<int32_t>(verifier, VT_STRIDE_W) &&
+ VerifyField<int32_t>(verifier, VT_STRIDE_H) &&
+ VerifyField<int32_t>(verifier, VT_FILTER_WIDTH) &&
+ VerifyField<int32_t>(verifier, VT_FILTER_HEIGHT) &&
+ VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION) && verifier.EndTable();
+ }
+ Pool2DOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(Pool2DOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<Pool2DOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const Pool2DOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct Pool2DOptionsBuilder
+{
+ typedef Pool2DOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_padding(circle::Padding padding)
+ {
+ fbb_.AddElement<int8_t>(Pool2DOptions::VT_PADDING, static_cast<int8_t>(padding), 0);
+ }
+ void add_stride_w(int32_t stride_w)
+ {
+ fbb_.AddElement<int32_t>(Pool2DOptions::VT_STRIDE_W, stride_w, 0);
+ }
+ void add_stride_h(int32_t stride_h)
+ {
+ fbb_.AddElement<int32_t>(Pool2DOptions::VT_STRIDE_H, stride_h, 0);
+ }
+ void add_filter_width(int32_t filter_width)
+ {
+ fbb_.AddElement<int32_t>(Pool2DOptions::VT_FILTER_WIDTH, filter_width, 0);
+ }
+ void add_filter_height(int32_t filter_height)
+ {
+ fbb_.AddElement<int32_t>(Pool2DOptions::VT_FILTER_HEIGHT, filter_height, 0);
+ }
+ void add_fused_activation_function(circle::ActivationFunctionType fused_activation_function)
+ {
+ fbb_.AddElement<int8_t>(Pool2DOptions::VT_FUSED_ACTIVATION_FUNCTION,
+ static_cast<int8_t>(fused_activation_function), 0);
+ }
+ explicit Pool2DOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<Pool2DOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Pool2DOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Pool2DOptions> CreatePool2DOptions(
+ flatbuffers::FlatBufferBuilder &_fbb, circle::Padding padding = circle::Padding_SAME,
+ int32_t stride_w = 0, int32_t stride_h = 0, int32_t filter_width = 0, int32_t filter_height = 0,
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE)
+{
+ Pool2DOptionsBuilder builder_(_fbb);
+ builder_.add_filter_height(filter_height);
+ builder_.add_filter_width(filter_width);
+ builder_.add_stride_h(stride_h);
+ builder_.add_stride_w(stride_w);
+ builder_.add_fused_activation_function(fused_activation_function);
+ builder_.add_padding(padding);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<Pool2DOptions>
+CreatePool2DOptions(flatbuffers::FlatBufferBuilder &_fbb, const Pool2DOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct DepthwiseConv2DOptionsT : public flatbuffers::NativeTable
+{
+ typedef DepthwiseConv2DOptions TableType;
+ circle::Padding padding = circle::Padding_SAME;
+ int32_t stride_w = 0;
+ int32_t stride_h = 0;
+ int32_t depth_multiplier = 0;
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
+ int32_t dilation_w_factor = 1;
+ int32_t dilation_h_factor = 1;
+};
+
+struct DepthwiseConv2DOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef DepthwiseConv2DOptionsT NativeTableType;
+ typedef DepthwiseConv2DOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_PADDING = 4,
+ VT_STRIDE_W = 6,
+ VT_STRIDE_H = 8,
+ VT_DEPTH_MULTIPLIER = 10,
+ VT_FUSED_ACTIVATION_FUNCTION = 12,
+ VT_DILATION_W_FACTOR = 14,
+ VT_DILATION_H_FACTOR = 16
+ };
+ circle::Padding padding() const
+ {
+ return static_cast<circle::Padding>(GetField<int8_t>(VT_PADDING, 0));
+ }
+ int32_t stride_w() const { return GetField<int32_t>(VT_STRIDE_W, 0); }
+ int32_t stride_h() const { return GetField<int32_t>(VT_STRIDE_H, 0); }
+ int32_t depth_multiplier() const { return GetField<int32_t>(VT_DEPTH_MULTIPLIER, 0); }
+ circle::ActivationFunctionType fused_activation_function() const
+ {
+ return static_cast<circle::ActivationFunctionType>(
+ GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+ }
+ int32_t dilation_w_factor() const { return GetField<int32_t>(VT_DILATION_W_FACTOR, 1); }
+ int32_t dilation_h_factor() const { return GetField<int32_t>(VT_DILATION_H_FACTOR, 1); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_PADDING) &&
+ VerifyField<int32_t>(verifier, VT_STRIDE_W) &&
+ VerifyField<int32_t>(verifier, VT_STRIDE_H) &&
+ VerifyField<int32_t>(verifier, VT_DEPTH_MULTIPLIER) &&
+ VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION) &&
+ VerifyField<int32_t>(verifier, VT_DILATION_W_FACTOR) &&
+ VerifyField<int32_t>(verifier, VT_DILATION_H_FACTOR) && verifier.EndTable();
+ }
+ DepthwiseConv2DOptionsT *
+ UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(DepthwiseConv2DOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<DepthwiseConv2DOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const DepthwiseConv2DOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct DepthwiseConv2DOptionsBuilder
+{
+ typedef DepthwiseConv2DOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_padding(circle::Padding padding)
+ {
+ fbb_.AddElement<int8_t>(DepthwiseConv2DOptions::VT_PADDING, static_cast<int8_t>(padding), 0);
+ }
+ void add_stride_w(int32_t stride_w)
+ {
+ fbb_.AddElement<int32_t>(DepthwiseConv2DOptions::VT_STRIDE_W, stride_w, 0);
+ }
+ void add_stride_h(int32_t stride_h)
+ {
+ fbb_.AddElement<int32_t>(DepthwiseConv2DOptions::VT_STRIDE_H, stride_h, 0);
+ }
+ void add_depth_multiplier(int32_t depth_multiplier)
+ {
+ fbb_.AddElement<int32_t>(DepthwiseConv2DOptions::VT_DEPTH_MULTIPLIER, depth_multiplier, 0);
+ }
+ void add_fused_activation_function(circle::ActivationFunctionType fused_activation_function)
+ {
+ fbb_.AddElement<int8_t>(DepthwiseConv2DOptions::VT_FUSED_ACTIVATION_FUNCTION,
+ static_cast<int8_t>(fused_activation_function), 0);
+ }
+ void add_dilation_w_factor(int32_t dilation_w_factor)
+ {
+ fbb_.AddElement<int32_t>(DepthwiseConv2DOptions::VT_DILATION_W_FACTOR, dilation_w_factor, 1);
+ }
+ void add_dilation_h_factor(int32_t dilation_h_factor)
+ {
+ fbb_.AddElement<int32_t>(DepthwiseConv2DOptions::VT_DILATION_H_FACTOR, dilation_h_factor, 1);
+ }
+ explicit DepthwiseConv2DOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<DepthwiseConv2DOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<DepthwiseConv2DOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<DepthwiseConv2DOptions> CreateDepthwiseConv2DOptions(
+ flatbuffers::FlatBufferBuilder &_fbb, circle::Padding padding = circle::Padding_SAME,
+ int32_t stride_w = 0, int32_t stride_h = 0, int32_t depth_multiplier = 0,
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE,
+ int32_t dilation_w_factor = 1, int32_t dilation_h_factor = 1)
+{
+ DepthwiseConv2DOptionsBuilder builder_(_fbb);
+ builder_.add_dilation_h_factor(dilation_h_factor);
+ builder_.add_dilation_w_factor(dilation_w_factor);
+ builder_.add_depth_multiplier(depth_multiplier);
+ builder_.add_stride_h(stride_h);
+ builder_.add_stride_w(stride_w);
+ builder_.add_fused_activation_function(fused_activation_function);
+ builder_.add_padding(padding);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<DepthwiseConv2DOptions>
+CreateDepthwiseConv2DOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ const DepthwiseConv2DOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct ConcatEmbeddingsOptionsT : public flatbuffers::NativeTable
+{
+ typedef ConcatEmbeddingsOptions TableType;
+ int32_t num_channels = 0;
+ std::vector<int32_t> num_columns_per_channel{};
+ std::vector<int32_t> embedding_dim_per_channel{};
+};
+
+struct ConcatEmbeddingsOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef ConcatEmbeddingsOptionsT NativeTableType;
+ typedef ConcatEmbeddingsOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_NUM_CHANNELS = 4,
+ VT_NUM_COLUMNS_PER_CHANNEL = 6,
+ VT_EMBEDDING_DIM_PER_CHANNEL = 8
+ };
+ int32_t num_channels() const { return GetField<int32_t>(VT_NUM_CHANNELS, 0); }
+ const flatbuffers::Vector<int32_t> *num_columns_per_channel() const
+ {
+ return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_NUM_COLUMNS_PER_CHANNEL);
+ }
+ const flatbuffers::Vector<int32_t> *embedding_dim_per_channel() const
+ {
+ return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_EMBEDDING_DIM_PER_CHANNEL);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_NUM_CHANNELS) &&
+ VerifyOffset(verifier, VT_NUM_COLUMNS_PER_CHANNEL) &&
+ verifier.VerifyVector(num_columns_per_channel()) &&
+ VerifyOffset(verifier, VT_EMBEDDING_DIM_PER_CHANNEL) &&
+ verifier.VerifyVector(embedding_dim_per_channel()) && verifier.EndTable();
+ }
+ ConcatEmbeddingsOptionsT *
+ UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(ConcatEmbeddingsOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<ConcatEmbeddingsOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const ConcatEmbeddingsOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct ConcatEmbeddingsOptionsBuilder
+{
+ typedef ConcatEmbeddingsOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_num_channels(int32_t num_channels)
+ {
+ fbb_.AddElement<int32_t>(ConcatEmbeddingsOptions::VT_NUM_CHANNELS, num_channels, 0);
+ }
+ void add_num_columns_per_channel(
+ flatbuffers::Offset<flatbuffers::Vector<int32_t>> num_columns_per_channel)
+ {
+ fbb_.AddOffset(ConcatEmbeddingsOptions::VT_NUM_COLUMNS_PER_CHANNEL, num_columns_per_channel);
+ }
+ void add_embedding_dim_per_channel(
+ flatbuffers::Offset<flatbuffers::Vector<int32_t>> embedding_dim_per_channel)
+ {
+ fbb_.AddOffset(ConcatEmbeddingsOptions::VT_EMBEDDING_DIM_PER_CHANNEL,
+ embedding_dim_per_channel);
+ }
+ explicit ConcatEmbeddingsOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<ConcatEmbeddingsOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<ConcatEmbeddingsOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<ConcatEmbeddingsOptions> CreateConcatEmbeddingsOptions(
+ flatbuffers::FlatBufferBuilder &_fbb, int32_t num_channels = 0,
+ flatbuffers::Offset<flatbuffers::Vector<int32_t>> num_columns_per_channel = 0,
+ flatbuffers::Offset<flatbuffers::Vector<int32_t>> embedding_dim_per_channel = 0)
+{
+ ConcatEmbeddingsOptionsBuilder builder_(_fbb);
+ builder_.add_embedding_dim_per_channel(embedding_dim_per_channel);
+ builder_.add_num_columns_per_channel(num_columns_per_channel);
+ builder_.add_num_channels(num_channels);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<ConcatEmbeddingsOptions>
+CreateConcatEmbeddingsOptionsDirect(flatbuffers::FlatBufferBuilder &_fbb, int32_t num_channels = 0,
+ const std::vector<int32_t> *num_columns_per_channel = nullptr,
+ const std::vector<int32_t> *embedding_dim_per_channel = nullptr)
+{
+ auto num_columns_per_channel__ =
+ num_columns_per_channel ? _fbb.CreateVector<int32_t>(*num_columns_per_channel) : 0;
+ auto embedding_dim_per_channel__ =
+ embedding_dim_per_channel ? _fbb.CreateVector<int32_t>(*embedding_dim_per_channel) : 0;
+ return circle::CreateConcatEmbeddingsOptions(_fbb, num_channels, num_columns_per_channel__,
+ embedding_dim_per_channel__);
+}
+
+flatbuffers::Offset<ConcatEmbeddingsOptions>
+CreateConcatEmbeddingsOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ const ConcatEmbeddingsOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct LSHProjectionOptionsT : public flatbuffers::NativeTable
+{
+ typedef LSHProjectionOptions TableType;
+ circle::LSHProjectionType type = circle::LSHProjectionType_UNKNOWN;
+};
+
+struct LSHProjectionOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef LSHProjectionOptionsT NativeTableType;
+ typedef LSHProjectionOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_TYPE = 4
+ };
+ circle::LSHProjectionType type() const
+ {
+ return static_cast<circle::LSHProjectionType>(GetField<int8_t>(VT_TYPE, 0));
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_TYPE) &&
+ verifier.EndTable();
+ }
+ LSHProjectionOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(LSHProjectionOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<LSHProjectionOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const LSHProjectionOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct LSHProjectionOptionsBuilder
+{
+ typedef LSHProjectionOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_type(circle::LSHProjectionType type)
+ {
+ fbb_.AddElement<int8_t>(LSHProjectionOptions::VT_TYPE, static_cast<int8_t>(type), 0);
+ }
+ explicit LSHProjectionOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<LSHProjectionOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<LSHProjectionOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<LSHProjectionOptions>
+CreateLSHProjectionOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ circle::LSHProjectionType type = circle::LSHProjectionType_UNKNOWN)
+{
+ LSHProjectionOptionsBuilder builder_(_fbb);
+ builder_.add_type(type);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<LSHProjectionOptions>
+CreateLSHProjectionOptions(flatbuffers::FlatBufferBuilder &_fbb, const LSHProjectionOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct SVDFOptionsT : public flatbuffers::NativeTable
+{
+ typedef SVDFOptions TableType;
+ int32_t rank = 0;
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
+ bool asymmetric_quantize_inputs = false;
+};
+
+struct SVDFOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef SVDFOptionsT NativeTableType;
+ typedef SVDFOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_RANK = 4,
+ VT_FUSED_ACTIVATION_FUNCTION = 6,
+ VT_ASYMMETRIC_QUANTIZE_INPUTS = 8
+ };
+ int32_t rank() const { return GetField<int32_t>(VT_RANK, 0); }
+ circle::ActivationFunctionType fused_activation_function() const
+ {
+ return static_cast<circle::ActivationFunctionType>(
+ GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+ }
+ bool asymmetric_quantize_inputs() const
+ {
+ return GetField<uint8_t>(VT_ASYMMETRIC_QUANTIZE_INPUTS, 0) != 0;
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_RANK) &&
+ VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION) &&
+ VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS) && verifier.EndTable();
+ }
+ SVDFOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(SVDFOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<SVDFOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const SVDFOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct SVDFOptionsBuilder
+{
+ typedef SVDFOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_rank(int32_t rank) { fbb_.AddElement<int32_t>(SVDFOptions::VT_RANK, rank, 0); }
+ void add_fused_activation_function(circle::ActivationFunctionType fused_activation_function)
+ {
+ fbb_.AddElement<int8_t>(SVDFOptions::VT_FUSED_ACTIVATION_FUNCTION,
+ static_cast<int8_t>(fused_activation_function), 0);
+ }
+ void add_asymmetric_quantize_inputs(bool asymmetric_quantize_inputs)
+ {
+ fbb_.AddElement<uint8_t>(SVDFOptions::VT_ASYMMETRIC_QUANTIZE_INPUTS,
+ static_cast<uint8_t>(asymmetric_quantize_inputs), 0);
+ }
+ explicit SVDFOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<SVDFOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<SVDFOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<SVDFOptions> CreateSVDFOptions(
+ flatbuffers::FlatBufferBuilder &_fbb, int32_t rank = 0,
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE,
+ bool asymmetric_quantize_inputs = false)
+{
+ SVDFOptionsBuilder builder_(_fbb);
+ builder_.add_rank(rank);
+ builder_.add_asymmetric_quantize_inputs(asymmetric_quantize_inputs);
+ builder_.add_fused_activation_function(fused_activation_function);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<SVDFOptions>
+CreateSVDFOptions(flatbuffers::FlatBufferBuilder &_fbb, const SVDFOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct RNNOptionsT : public flatbuffers::NativeTable
+{
+ typedef RNNOptions TableType;
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
+ bool asymmetric_quantize_inputs = false;
+};
+
+struct RNNOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef RNNOptionsT NativeTableType;
+ typedef RNNOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_FUSED_ACTIVATION_FUNCTION = 4,
+ VT_ASYMMETRIC_QUANTIZE_INPUTS = 6
+ };
+ circle::ActivationFunctionType fused_activation_function() const
+ {
+ return static_cast<circle::ActivationFunctionType>(
+ GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+ }
+ bool asymmetric_quantize_inputs() const
+ {
+ return GetField<uint8_t>(VT_ASYMMETRIC_QUANTIZE_INPUTS, 0) != 0;
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) &&
+ VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION) &&
+ VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS) && verifier.EndTable();
+ }
+ RNNOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(RNNOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<RNNOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const RNNOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct RNNOptionsBuilder
+{
+ typedef RNNOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_fused_activation_function(circle::ActivationFunctionType fused_activation_function)
+ {
+ fbb_.AddElement<int8_t>(RNNOptions::VT_FUSED_ACTIVATION_FUNCTION,
+ static_cast<int8_t>(fused_activation_function), 0);
+ }
+ void add_asymmetric_quantize_inputs(bool asymmetric_quantize_inputs)
+ {
+ fbb_.AddElement<uint8_t>(RNNOptions::VT_ASYMMETRIC_QUANTIZE_INPUTS,
+ static_cast<uint8_t>(asymmetric_quantize_inputs), 0);
+ }
+ explicit RNNOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<RNNOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<RNNOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<RNNOptions> CreateRNNOptions(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE,
+ bool asymmetric_quantize_inputs = false)
+{
+ RNNOptionsBuilder builder_(_fbb);
+ builder_.add_asymmetric_quantize_inputs(asymmetric_quantize_inputs);
+ builder_.add_fused_activation_function(fused_activation_function);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<RNNOptions>
+CreateRNNOptions(flatbuffers::FlatBufferBuilder &_fbb, const RNNOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct SequenceRNNOptionsT : public flatbuffers::NativeTable
+{
+ typedef SequenceRNNOptions TableType;
+ bool time_major = false;
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
+ bool asymmetric_quantize_inputs = false;
+};
+
+struct SequenceRNNOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef SequenceRNNOptionsT NativeTableType;
+ typedef SequenceRNNOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_TIME_MAJOR = 4,
+ VT_FUSED_ACTIVATION_FUNCTION = 6,
+ VT_ASYMMETRIC_QUANTIZE_INPUTS = 8
+ };
+ bool time_major() const { return GetField<uint8_t>(VT_TIME_MAJOR, 0) != 0; }
+ circle::ActivationFunctionType fused_activation_function() const
+ {
+ return static_cast<circle::ActivationFunctionType>(
+ GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+ }
+ bool asymmetric_quantize_inputs() const
+ {
+ return GetField<uint8_t>(VT_ASYMMETRIC_QUANTIZE_INPUTS, 0) != 0;
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<uint8_t>(verifier, VT_TIME_MAJOR) &&
+ VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION) &&
+ VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS) && verifier.EndTable();
+ }
+ SequenceRNNOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(SequenceRNNOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<SequenceRNNOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const SequenceRNNOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct SequenceRNNOptionsBuilder
+{
+ typedef SequenceRNNOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_time_major(bool time_major)
+ {
+ fbb_.AddElement<uint8_t>(SequenceRNNOptions::VT_TIME_MAJOR, static_cast<uint8_t>(time_major),
+ 0);
+ }
+ void add_fused_activation_function(circle::ActivationFunctionType fused_activation_function)
+ {
+ fbb_.AddElement<int8_t>(SequenceRNNOptions::VT_FUSED_ACTIVATION_FUNCTION,
+ static_cast<int8_t>(fused_activation_function), 0);
+ }
+ void add_asymmetric_quantize_inputs(bool asymmetric_quantize_inputs)
+ {
+ fbb_.AddElement<uint8_t>(SequenceRNNOptions::VT_ASYMMETRIC_QUANTIZE_INPUTS,
+ static_cast<uint8_t>(asymmetric_quantize_inputs), 0);
+ }
+ explicit SequenceRNNOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<SequenceRNNOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<SequenceRNNOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<SequenceRNNOptions> CreateSequenceRNNOptions(
+ flatbuffers::FlatBufferBuilder &_fbb, bool time_major = false,
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE,
+ bool asymmetric_quantize_inputs = false)
+{
+ SequenceRNNOptionsBuilder builder_(_fbb);
+ builder_.add_asymmetric_quantize_inputs(asymmetric_quantize_inputs);
+ builder_.add_fused_activation_function(fused_activation_function);
+ builder_.add_time_major(time_major);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<SequenceRNNOptions>
+CreateSequenceRNNOptions(flatbuffers::FlatBufferBuilder &_fbb, const SequenceRNNOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct BidirectionalSequenceRNNOptionsT : public flatbuffers::NativeTable
+{
+ typedef BidirectionalSequenceRNNOptions TableType;
+ bool time_major = false;
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
+ bool merge_outputs = false;
+ bool asymmetric_quantize_inputs = false;
+};
+
+struct BidirectionalSequenceRNNOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef BidirectionalSequenceRNNOptionsT NativeTableType;
+ typedef BidirectionalSequenceRNNOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_TIME_MAJOR = 4,
+ VT_FUSED_ACTIVATION_FUNCTION = 6,
+ VT_MERGE_OUTPUTS = 8,
+ VT_ASYMMETRIC_QUANTIZE_INPUTS = 10
+ };
+ bool time_major() const { return GetField<uint8_t>(VT_TIME_MAJOR, 0) != 0; }
+ circle::ActivationFunctionType fused_activation_function() const
+ {
+ return static_cast<circle::ActivationFunctionType>(
+ GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+ }
+ bool merge_outputs() const { return GetField<uint8_t>(VT_MERGE_OUTPUTS, 0) != 0; }
+ bool asymmetric_quantize_inputs() const
+ {
+ return GetField<uint8_t>(VT_ASYMMETRIC_QUANTIZE_INPUTS, 0) != 0;
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<uint8_t>(verifier, VT_TIME_MAJOR) &&
+ VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION) &&
+ VerifyField<uint8_t>(verifier, VT_MERGE_OUTPUTS) &&
+ VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS) && verifier.EndTable();
+ }
+ BidirectionalSequenceRNNOptionsT *
+ UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(BidirectionalSequenceRNNOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<BidirectionalSequenceRNNOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const BidirectionalSequenceRNNOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct BidirectionalSequenceRNNOptionsBuilder
+{
+ typedef BidirectionalSequenceRNNOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_time_major(bool time_major)
+ {
+ fbb_.AddElement<uint8_t>(BidirectionalSequenceRNNOptions::VT_TIME_MAJOR,
+ static_cast<uint8_t>(time_major), 0);
+ }
+ void add_fused_activation_function(circle::ActivationFunctionType fused_activation_function)
+ {
+ fbb_.AddElement<int8_t>(BidirectionalSequenceRNNOptions::VT_FUSED_ACTIVATION_FUNCTION,
+ static_cast<int8_t>(fused_activation_function), 0);
+ }
+ void add_merge_outputs(bool merge_outputs)
+ {
+ fbb_.AddElement<uint8_t>(BidirectionalSequenceRNNOptions::VT_MERGE_OUTPUTS,
+ static_cast<uint8_t>(merge_outputs), 0);
+ }
+ void add_asymmetric_quantize_inputs(bool asymmetric_quantize_inputs)
+ {
+ fbb_.AddElement<uint8_t>(BidirectionalSequenceRNNOptions::VT_ASYMMETRIC_QUANTIZE_INPUTS,
+ static_cast<uint8_t>(asymmetric_quantize_inputs), 0);
+ }
+ explicit BidirectionalSequenceRNNOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<BidirectionalSequenceRNNOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<BidirectionalSequenceRNNOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<BidirectionalSequenceRNNOptions> CreateBidirectionalSequenceRNNOptions(
+ flatbuffers::FlatBufferBuilder &_fbb, bool time_major = false,
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE,
+ bool merge_outputs = false, bool asymmetric_quantize_inputs = false)
+{
+ BidirectionalSequenceRNNOptionsBuilder builder_(_fbb);
+ builder_.add_asymmetric_quantize_inputs(asymmetric_quantize_inputs);
+ builder_.add_merge_outputs(merge_outputs);
+ builder_.add_fused_activation_function(fused_activation_function);
+ builder_.add_time_major(time_major);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<BidirectionalSequenceRNNOptions>
+CreateBidirectionalSequenceRNNOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ const BidirectionalSequenceRNNOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct FullyConnectedOptionsT : public flatbuffers::NativeTable
+{
+ typedef FullyConnectedOptions TableType;
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
+ circle::FullyConnectedOptionsWeightsFormat weights_format =
+ circle::FullyConnectedOptionsWeightsFormat_DEFAULT;
+ bool keep_num_dims = false;
+ bool asymmetric_quantize_inputs = false;
+};
+
+struct FullyConnectedOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef FullyConnectedOptionsT NativeTableType;
+ typedef FullyConnectedOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_FUSED_ACTIVATION_FUNCTION = 4,
+ VT_WEIGHTS_FORMAT = 6,
+ VT_KEEP_NUM_DIMS = 8,
+ VT_ASYMMETRIC_QUANTIZE_INPUTS = 10
+ };
+ circle::ActivationFunctionType fused_activation_function() const
+ {
+ return static_cast<circle::ActivationFunctionType>(
+ GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+ }
+ circle::FullyConnectedOptionsWeightsFormat weights_format() const
+ {
+ return static_cast<circle::FullyConnectedOptionsWeightsFormat>(
+ GetField<int8_t>(VT_WEIGHTS_FORMAT, 0));
+ }
+ bool keep_num_dims() const { return GetField<uint8_t>(VT_KEEP_NUM_DIMS, 0) != 0; }
+ bool asymmetric_quantize_inputs() const
+ {
+ return GetField<uint8_t>(VT_ASYMMETRIC_QUANTIZE_INPUTS, 0) != 0;
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) &&
+ VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION) &&
+ VerifyField<int8_t>(verifier, VT_WEIGHTS_FORMAT) &&
+ VerifyField<uint8_t>(verifier, VT_KEEP_NUM_DIMS) &&
+ VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS) && verifier.EndTable();
+ }
+ FullyConnectedOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(FullyConnectedOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<FullyConnectedOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const FullyConnectedOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct FullyConnectedOptionsBuilder
+{
+ typedef FullyConnectedOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_fused_activation_function(circle::ActivationFunctionType fused_activation_function)
+ {
+ fbb_.AddElement<int8_t>(FullyConnectedOptions::VT_FUSED_ACTIVATION_FUNCTION,
+ static_cast<int8_t>(fused_activation_function), 0);
+ }
+ void add_weights_format(circle::FullyConnectedOptionsWeightsFormat weights_format)
+ {
+ fbb_.AddElement<int8_t>(FullyConnectedOptions::VT_WEIGHTS_FORMAT,
+ static_cast<int8_t>(weights_format), 0);
+ }
+ void add_keep_num_dims(bool keep_num_dims)
+ {
+ fbb_.AddElement<uint8_t>(FullyConnectedOptions::VT_KEEP_NUM_DIMS,
+ static_cast<uint8_t>(keep_num_dims), 0);
+ }
+ void add_asymmetric_quantize_inputs(bool asymmetric_quantize_inputs)
+ {
+ fbb_.AddElement<uint8_t>(FullyConnectedOptions::VT_ASYMMETRIC_QUANTIZE_INPUTS,
+ static_cast<uint8_t>(asymmetric_quantize_inputs), 0);
+ }
+ explicit FullyConnectedOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<FullyConnectedOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<FullyConnectedOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<FullyConnectedOptions> CreateFullyConnectedOptions(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE,
+ circle::FullyConnectedOptionsWeightsFormat weights_format =
+ circle::FullyConnectedOptionsWeightsFormat_DEFAULT,
+ bool keep_num_dims = false, bool asymmetric_quantize_inputs = false)
+{
+ FullyConnectedOptionsBuilder builder_(_fbb);
+ builder_.add_asymmetric_quantize_inputs(asymmetric_quantize_inputs);
+ builder_.add_keep_num_dims(keep_num_dims);
+ builder_.add_weights_format(weights_format);
+ builder_.add_fused_activation_function(fused_activation_function);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<FullyConnectedOptions>
+CreateFullyConnectedOptions(flatbuffers::FlatBufferBuilder &_fbb, const FullyConnectedOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct SoftmaxOptionsT : public flatbuffers::NativeTable
+{
+ typedef SoftmaxOptions TableType;
+ float beta = 0.0f;
+};
+
+struct SoftmaxOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef SoftmaxOptionsT NativeTableType;
+ typedef SoftmaxOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_BETA = 4
+ };
+ float beta() const { return GetField<float>(VT_BETA, 0.0f); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<float>(verifier, VT_BETA) &&
+ verifier.EndTable();
+ }
+ SoftmaxOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(SoftmaxOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<SoftmaxOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const SoftmaxOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct SoftmaxOptionsBuilder
+{
+ typedef SoftmaxOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_beta(float beta) { fbb_.AddElement<float>(SoftmaxOptions::VT_BETA, beta, 0.0f); }
+ explicit SoftmaxOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<SoftmaxOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<SoftmaxOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<SoftmaxOptions>
+CreateSoftmaxOptions(flatbuffers::FlatBufferBuilder &_fbb, float beta = 0.0f)
+{
+ SoftmaxOptionsBuilder builder_(_fbb);
+ builder_.add_beta(beta);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<SoftmaxOptions>
+CreateSoftmaxOptions(flatbuffers::FlatBufferBuilder &_fbb, const SoftmaxOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct ConcatenationOptionsT : public flatbuffers::NativeTable
+{
+ typedef ConcatenationOptions TableType;
+ int32_t axis = 0;
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
+};
+
+struct ConcatenationOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef ConcatenationOptionsT NativeTableType;
+ typedef ConcatenationOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_AXIS = 4,
+ VT_FUSED_ACTIVATION_FUNCTION = 6
+ };
+ int32_t axis() const { return GetField<int32_t>(VT_AXIS, 0); }
+ circle::ActivationFunctionType fused_activation_function() const
+ {
+ return static_cast<circle::ActivationFunctionType>(
+ GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_AXIS) &&
+ VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION) && verifier.EndTable();
+ }
+ ConcatenationOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(ConcatenationOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<ConcatenationOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const ConcatenationOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct ConcatenationOptionsBuilder
+{
+ typedef ConcatenationOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_axis(int32_t axis) { fbb_.AddElement<int32_t>(ConcatenationOptions::VT_AXIS, axis, 0); }
+ void add_fused_activation_function(circle::ActivationFunctionType fused_activation_function)
+ {
+ fbb_.AddElement<int8_t>(ConcatenationOptions::VT_FUSED_ACTIVATION_FUNCTION,
+ static_cast<int8_t>(fused_activation_function), 0);
+ }
+ explicit ConcatenationOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<ConcatenationOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<ConcatenationOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<ConcatenationOptions> CreateConcatenationOptions(
+ flatbuffers::FlatBufferBuilder &_fbb, int32_t axis = 0,
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE)
+{
+ ConcatenationOptionsBuilder builder_(_fbb);
+ builder_.add_axis(axis);
+ builder_.add_fused_activation_function(fused_activation_function);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<ConcatenationOptions>
+CreateConcatenationOptions(flatbuffers::FlatBufferBuilder &_fbb, const ConcatenationOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct AddOptionsT : public flatbuffers::NativeTable
+{
+ typedef AddOptions TableType;
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
+ bool pot_scale_int16 = true;
+};
+
+struct AddOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef AddOptionsT NativeTableType;
+ typedef AddOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_FUSED_ACTIVATION_FUNCTION = 4,
+ VT_POT_SCALE_INT16 = 6
+ };
+ circle::ActivationFunctionType fused_activation_function() const
+ {
+ return static_cast<circle::ActivationFunctionType>(
+ GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+ }
+ bool pot_scale_int16() const { return GetField<uint8_t>(VT_POT_SCALE_INT16, 1) != 0; }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) &&
+ VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION) &&
+ VerifyField<uint8_t>(verifier, VT_POT_SCALE_INT16) && verifier.EndTable();
+ }
+ AddOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(AddOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<AddOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const AddOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct AddOptionsBuilder
+{
+ typedef AddOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_fused_activation_function(circle::ActivationFunctionType fused_activation_function)
+ {
+ fbb_.AddElement<int8_t>(AddOptions::VT_FUSED_ACTIVATION_FUNCTION,
+ static_cast<int8_t>(fused_activation_function), 0);
+ }
+ void add_pot_scale_int16(bool pot_scale_int16)
+ {
+ fbb_.AddElement<uint8_t>(AddOptions::VT_POT_SCALE_INT16, static_cast<uint8_t>(pot_scale_int16),
+ 1);
+ }
+ explicit AddOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<AddOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<AddOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<AddOptions> CreateAddOptions(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE,
+ bool pot_scale_int16 = true)
+{
+ AddOptionsBuilder builder_(_fbb);
+ builder_.add_pot_scale_int16(pot_scale_int16);
+ builder_.add_fused_activation_function(fused_activation_function);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<AddOptions>
+CreateAddOptions(flatbuffers::FlatBufferBuilder &_fbb, const AddOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct MulOptionsT : public flatbuffers::NativeTable
+{
+ typedef MulOptions TableType;
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
+};
+
+struct MulOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef MulOptionsT NativeTableType;
+ typedef MulOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_FUSED_ACTIVATION_FUNCTION = 4
+ };
+ circle::ActivationFunctionType fused_activation_function() const
+ {
+ return static_cast<circle::ActivationFunctionType>(
+ GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) &&
+ VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION) && verifier.EndTable();
+ }
+ MulOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(MulOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<MulOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const MulOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct MulOptionsBuilder
+{
+ typedef MulOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_fused_activation_function(circle::ActivationFunctionType fused_activation_function)
+ {
+ fbb_.AddElement<int8_t>(MulOptions::VT_FUSED_ACTIVATION_FUNCTION,
+ static_cast<int8_t>(fused_activation_function), 0);
+ }
+ explicit MulOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<MulOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<MulOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<MulOptions> CreateMulOptions(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE)
+{
+ MulOptionsBuilder builder_(_fbb);
+ builder_.add_fused_activation_function(fused_activation_function);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<MulOptions>
+CreateMulOptions(flatbuffers::FlatBufferBuilder &_fbb, const MulOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct L2NormOptionsT : public flatbuffers::NativeTable
+{
+ typedef L2NormOptions TableType;
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
+};
+
+struct L2NormOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef L2NormOptionsT NativeTableType;
+ typedef L2NormOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_FUSED_ACTIVATION_FUNCTION = 4
+ };
+ circle::ActivationFunctionType fused_activation_function() const
+ {
+ return static_cast<circle::ActivationFunctionType>(
+ GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) &&
+ VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION) && verifier.EndTable();
+ }
+ L2NormOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(L2NormOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<L2NormOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const L2NormOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct L2NormOptionsBuilder
+{
+ typedef L2NormOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_fused_activation_function(circle::ActivationFunctionType fused_activation_function)
+ {
+ fbb_.AddElement<int8_t>(L2NormOptions::VT_FUSED_ACTIVATION_FUNCTION,
+ static_cast<int8_t>(fused_activation_function), 0);
+ }
+ explicit L2NormOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<L2NormOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<L2NormOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<L2NormOptions> CreateL2NormOptions(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE)
+{
+ L2NormOptionsBuilder builder_(_fbb);
+ builder_.add_fused_activation_function(fused_activation_function);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<L2NormOptions>
+CreateL2NormOptions(flatbuffers::FlatBufferBuilder &_fbb, const L2NormOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct LocalResponseNormalizationOptionsT : public flatbuffers::NativeTable
+{
+ typedef LocalResponseNormalizationOptions TableType;
+ int32_t radius = 0;
+ float bias = 0.0f;
+ float alpha = 0.0f;
+ float beta = 0.0f;
+};
+
+struct LocalResponseNormalizationOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef LocalResponseNormalizationOptionsT NativeTableType;
+ typedef LocalResponseNormalizationOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_RADIUS = 4,
+ VT_BIAS = 6,
+ VT_ALPHA = 8,
+ VT_BETA = 10
+ };
+ int32_t radius() const { return GetField<int32_t>(VT_RADIUS, 0); }
+ float bias() const { return GetField<float>(VT_BIAS, 0.0f); }
+ float alpha() const { return GetField<float>(VT_ALPHA, 0.0f); }
+ float beta() const { return GetField<float>(VT_BETA, 0.0f); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_RADIUS) &&
+ VerifyField<float>(verifier, VT_BIAS) && VerifyField<float>(verifier, VT_ALPHA) &&
+ VerifyField<float>(verifier, VT_BETA) && verifier.EndTable();
+ }
+ LocalResponseNormalizationOptionsT *
+ UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(LocalResponseNormalizationOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<LocalResponseNormalizationOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const LocalResponseNormalizationOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct LocalResponseNormalizationOptionsBuilder
+{
+ typedef LocalResponseNormalizationOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_radius(int32_t radius)
+ {
+ fbb_.AddElement<int32_t>(LocalResponseNormalizationOptions::VT_RADIUS, radius, 0);
+ }
+ void add_bias(float bias)
+ {
+ fbb_.AddElement<float>(LocalResponseNormalizationOptions::VT_BIAS, bias, 0.0f);
+ }
+ void add_alpha(float alpha)
+ {
+ fbb_.AddElement<float>(LocalResponseNormalizationOptions::VT_ALPHA, alpha, 0.0f);
+ }
+ void add_beta(float beta)
+ {
+ fbb_.AddElement<float>(LocalResponseNormalizationOptions::VT_BETA, beta, 0.0f);
+ }
+ explicit LocalResponseNormalizationOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<LocalResponseNormalizationOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<LocalResponseNormalizationOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<LocalResponseNormalizationOptions>
+CreateLocalResponseNormalizationOptions(flatbuffers::FlatBufferBuilder &_fbb, int32_t radius = 0,
+ float bias = 0.0f, float alpha = 0.0f, float beta = 0.0f)
+{
+ LocalResponseNormalizationOptionsBuilder builder_(_fbb);
+ builder_.add_beta(beta);
+ builder_.add_alpha(alpha);
+ builder_.add_bias(bias);
+ builder_.add_radius(radius);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<LocalResponseNormalizationOptions> CreateLocalResponseNormalizationOptions(
+ flatbuffers::FlatBufferBuilder &_fbb, const LocalResponseNormalizationOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct LSTMOptionsT : public flatbuffers::NativeTable
+{
+ typedef LSTMOptions TableType;
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
+ float cell_clip = 0.0f;
+ float proj_clip = 0.0f;
+ circle::LSTMKernelType kernel_type = circle::LSTMKernelType_FULL;
+ bool asymmetric_quantize_inputs = false;
+};
+
+struct LSTMOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef LSTMOptionsT NativeTableType;
+ typedef LSTMOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_FUSED_ACTIVATION_FUNCTION = 4,
+ VT_CELL_CLIP = 6,
+ VT_PROJ_CLIP = 8,
+ VT_KERNEL_TYPE = 10,
+ VT_ASYMMETRIC_QUANTIZE_INPUTS = 12
+ };
+ circle::ActivationFunctionType fused_activation_function() const
+ {
+ return static_cast<circle::ActivationFunctionType>(
+ GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+ }
+ float cell_clip() const { return GetField<float>(VT_CELL_CLIP, 0.0f); }
+ float proj_clip() const { return GetField<float>(VT_PROJ_CLIP, 0.0f); }
+ circle::LSTMKernelType kernel_type() const
+ {
+ return static_cast<circle::LSTMKernelType>(GetField<int8_t>(VT_KERNEL_TYPE, 0));
+ }
+ bool asymmetric_quantize_inputs() const
+ {
+ return GetField<uint8_t>(VT_ASYMMETRIC_QUANTIZE_INPUTS, 0) != 0;
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) &&
+ VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION) &&
+ VerifyField<float>(verifier, VT_CELL_CLIP) &&
+ VerifyField<float>(verifier, VT_PROJ_CLIP) &&
+ VerifyField<int8_t>(verifier, VT_KERNEL_TYPE) &&
+ VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS) && verifier.EndTable();
+ }
+ LSTMOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(LSTMOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<LSTMOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const LSTMOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct LSTMOptionsBuilder
+{
+ typedef LSTMOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_fused_activation_function(circle::ActivationFunctionType fused_activation_function)
+ {
+ fbb_.AddElement<int8_t>(LSTMOptions::VT_FUSED_ACTIVATION_FUNCTION,
+ static_cast<int8_t>(fused_activation_function), 0);
+ }
+ void add_cell_clip(float cell_clip)
+ {
+ fbb_.AddElement<float>(LSTMOptions::VT_CELL_CLIP, cell_clip, 0.0f);
+ }
+ void add_proj_clip(float proj_clip)
+ {
+ fbb_.AddElement<float>(LSTMOptions::VT_PROJ_CLIP, proj_clip, 0.0f);
+ }
+ void add_kernel_type(circle::LSTMKernelType kernel_type)
+ {
+ fbb_.AddElement<int8_t>(LSTMOptions::VT_KERNEL_TYPE, static_cast<int8_t>(kernel_type), 0);
+ }
+ void add_asymmetric_quantize_inputs(bool asymmetric_quantize_inputs)
+ {
+ fbb_.AddElement<uint8_t>(LSTMOptions::VT_ASYMMETRIC_QUANTIZE_INPUTS,
+ static_cast<uint8_t>(asymmetric_quantize_inputs), 0);
+ }
+ explicit LSTMOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<LSTMOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<LSTMOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<LSTMOptions> CreateLSTMOptions(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE,
+ float cell_clip = 0.0f, float proj_clip = 0.0f,
+ circle::LSTMKernelType kernel_type = circle::LSTMKernelType_FULL,
+ bool asymmetric_quantize_inputs = false)
+{
+ LSTMOptionsBuilder builder_(_fbb);
+ builder_.add_proj_clip(proj_clip);
+ builder_.add_cell_clip(cell_clip);
+ builder_.add_asymmetric_quantize_inputs(asymmetric_quantize_inputs);
+ builder_.add_kernel_type(kernel_type);
+ builder_.add_fused_activation_function(fused_activation_function);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<LSTMOptions>
+CreateLSTMOptions(flatbuffers::FlatBufferBuilder &_fbb, const LSTMOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct UnidirectionalSequenceLSTMOptionsT : public flatbuffers::NativeTable
+{
+ typedef UnidirectionalSequenceLSTMOptions TableType;
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
+ float cell_clip = 0.0f;
+ float proj_clip = 0.0f;
+ bool time_major = false;
+ bool asymmetric_quantize_inputs = false;
+};
+
+struct UnidirectionalSequenceLSTMOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef UnidirectionalSequenceLSTMOptionsT NativeTableType;
+ typedef UnidirectionalSequenceLSTMOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_FUSED_ACTIVATION_FUNCTION = 4,
+ VT_CELL_CLIP = 6,
+ VT_PROJ_CLIP = 8,
+ VT_TIME_MAJOR = 10,
+ VT_ASYMMETRIC_QUANTIZE_INPUTS = 12
+ };
+ circle::ActivationFunctionType fused_activation_function() const
+ {
+ return static_cast<circle::ActivationFunctionType>(
+ GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+ }
+ float cell_clip() const { return GetField<float>(VT_CELL_CLIP, 0.0f); }
+ float proj_clip() const { return GetField<float>(VT_PROJ_CLIP, 0.0f); }
+ bool time_major() const { return GetField<uint8_t>(VT_TIME_MAJOR, 0) != 0; }
+ bool asymmetric_quantize_inputs() const
+ {
+ return GetField<uint8_t>(VT_ASYMMETRIC_QUANTIZE_INPUTS, 0) != 0;
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) &&
+ VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION) &&
+ VerifyField<float>(verifier, VT_CELL_CLIP) &&
+ VerifyField<float>(verifier, VT_PROJ_CLIP) &&
+ VerifyField<uint8_t>(verifier, VT_TIME_MAJOR) &&
+ VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS) && verifier.EndTable();
+ }
+ UnidirectionalSequenceLSTMOptionsT *
+ UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(UnidirectionalSequenceLSTMOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<UnidirectionalSequenceLSTMOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const UnidirectionalSequenceLSTMOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct UnidirectionalSequenceLSTMOptionsBuilder
+{
+ typedef UnidirectionalSequenceLSTMOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_fused_activation_function(circle::ActivationFunctionType fused_activation_function)
+ {
+ fbb_.AddElement<int8_t>(UnidirectionalSequenceLSTMOptions::VT_FUSED_ACTIVATION_FUNCTION,
+ static_cast<int8_t>(fused_activation_function), 0);
+ }
+ void add_cell_clip(float cell_clip)
+ {
+ fbb_.AddElement<float>(UnidirectionalSequenceLSTMOptions::VT_CELL_CLIP, cell_clip, 0.0f);
+ }
+ void add_proj_clip(float proj_clip)
+ {
+ fbb_.AddElement<float>(UnidirectionalSequenceLSTMOptions::VT_PROJ_CLIP, proj_clip, 0.0f);
+ }
+ void add_time_major(bool time_major)
+ {
+ fbb_.AddElement<uint8_t>(UnidirectionalSequenceLSTMOptions::VT_TIME_MAJOR,
+ static_cast<uint8_t>(time_major), 0);
+ }
+ void add_asymmetric_quantize_inputs(bool asymmetric_quantize_inputs)
+ {
+ fbb_.AddElement<uint8_t>(UnidirectionalSequenceLSTMOptions::VT_ASYMMETRIC_QUANTIZE_INPUTS,
+ static_cast<uint8_t>(asymmetric_quantize_inputs), 0);
+ }
+ explicit UnidirectionalSequenceLSTMOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<UnidirectionalSequenceLSTMOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<UnidirectionalSequenceLSTMOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<UnidirectionalSequenceLSTMOptions>
+CreateUnidirectionalSequenceLSTMOptions(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE,
+ float cell_clip = 0.0f, float proj_clip = 0.0f, bool time_major = false,
+ bool asymmetric_quantize_inputs = false)
+{
+ UnidirectionalSequenceLSTMOptionsBuilder builder_(_fbb);
+ builder_.add_proj_clip(proj_clip);
+ builder_.add_cell_clip(cell_clip);
+ builder_.add_asymmetric_quantize_inputs(asymmetric_quantize_inputs);
+ builder_.add_time_major(time_major);
+ builder_.add_fused_activation_function(fused_activation_function);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<UnidirectionalSequenceLSTMOptions> CreateUnidirectionalSequenceLSTMOptions(
+ flatbuffers::FlatBufferBuilder &_fbb, const UnidirectionalSequenceLSTMOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct BidirectionalSequenceLSTMOptionsT : public flatbuffers::NativeTable
+{
+ typedef BidirectionalSequenceLSTMOptions TableType;
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
+ float cell_clip = 0.0f;
+ float proj_clip = 0.0f;
+ bool merge_outputs = false;
+ bool time_major = true;
+ bool asymmetric_quantize_inputs = false;
+};
+
+struct BidirectionalSequenceLSTMOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef BidirectionalSequenceLSTMOptionsT NativeTableType;
+ typedef BidirectionalSequenceLSTMOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_FUSED_ACTIVATION_FUNCTION = 4,
+ VT_CELL_CLIP = 6,
+ VT_PROJ_CLIP = 8,
+ VT_MERGE_OUTPUTS = 10,
+ VT_TIME_MAJOR = 12,
+ VT_ASYMMETRIC_QUANTIZE_INPUTS = 14
+ };
+ circle::ActivationFunctionType fused_activation_function() const
+ {
+ return static_cast<circle::ActivationFunctionType>(
+ GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+ }
+ float cell_clip() const { return GetField<float>(VT_CELL_CLIP, 0.0f); }
+ float proj_clip() const { return GetField<float>(VT_PROJ_CLIP, 0.0f); }
+ bool merge_outputs() const { return GetField<uint8_t>(VT_MERGE_OUTPUTS, 0) != 0; }
+ bool time_major() const { return GetField<uint8_t>(VT_TIME_MAJOR, 1) != 0; }
+ bool asymmetric_quantize_inputs() const
+ {
+ return GetField<uint8_t>(VT_ASYMMETRIC_QUANTIZE_INPUTS, 0) != 0;
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) &&
+ VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION) &&
+ VerifyField<float>(verifier, VT_CELL_CLIP) &&
+ VerifyField<float>(verifier, VT_PROJ_CLIP) &&
+ VerifyField<uint8_t>(verifier, VT_MERGE_OUTPUTS) &&
+ VerifyField<uint8_t>(verifier, VT_TIME_MAJOR) &&
+ VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS) && verifier.EndTable();
+ }
+ BidirectionalSequenceLSTMOptionsT *
+ UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(BidirectionalSequenceLSTMOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<BidirectionalSequenceLSTMOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const BidirectionalSequenceLSTMOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct BidirectionalSequenceLSTMOptionsBuilder
+{
+ typedef BidirectionalSequenceLSTMOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_fused_activation_function(circle::ActivationFunctionType fused_activation_function)
+ {
+ fbb_.AddElement<int8_t>(BidirectionalSequenceLSTMOptions::VT_FUSED_ACTIVATION_FUNCTION,
+ static_cast<int8_t>(fused_activation_function), 0);
+ }
+ void add_cell_clip(float cell_clip)
+ {
+ fbb_.AddElement<float>(BidirectionalSequenceLSTMOptions::VT_CELL_CLIP, cell_clip, 0.0f);
+ }
+ void add_proj_clip(float proj_clip)
+ {
+ fbb_.AddElement<float>(BidirectionalSequenceLSTMOptions::VT_PROJ_CLIP, proj_clip, 0.0f);
+ }
+ void add_merge_outputs(bool merge_outputs)
+ {
+ fbb_.AddElement<uint8_t>(BidirectionalSequenceLSTMOptions::VT_MERGE_OUTPUTS,
+ static_cast<uint8_t>(merge_outputs), 0);
+ }
+ void add_time_major(bool time_major)
+ {
+ fbb_.AddElement<uint8_t>(BidirectionalSequenceLSTMOptions::VT_TIME_MAJOR,
+ static_cast<uint8_t>(time_major), 1);
+ }
+ void add_asymmetric_quantize_inputs(bool asymmetric_quantize_inputs)
+ {
+ fbb_.AddElement<uint8_t>(BidirectionalSequenceLSTMOptions::VT_ASYMMETRIC_QUANTIZE_INPUTS,
+ static_cast<uint8_t>(asymmetric_quantize_inputs), 0);
+ }
+ explicit BidirectionalSequenceLSTMOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<BidirectionalSequenceLSTMOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<BidirectionalSequenceLSTMOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<BidirectionalSequenceLSTMOptions> CreateBidirectionalSequenceLSTMOptions(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE,
+ float cell_clip = 0.0f, float proj_clip = 0.0f, bool merge_outputs = false,
+ bool time_major = true, bool asymmetric_quantize_inputs = false)
+{
+ BidirectionalSequenceLSTMOptionsBuilder builder_(_fbb);
+ builder_.add_proj_clip(proj_clip);
+ builder_.add_cell_clip(cell_clip);
+ builder_.add_asymmetric_quantize_inputs(asymmetric_quantize_inputs);
+ builder_.add_time_major(time_major);
+ builder_.add_merge_outputs(merge_outputs);
+ builder_.add_fused_activation_function(fused_activation_function);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<BidirectionalSequenceLSTMOptions>
+CreateBidirectionalSequenceLSTMOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ const BidirectionalSequenceLSTMOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct ResizeBilinearOptionsT : public flatbuffers::NativeTable
+{
+ typedef ResizeBilinearOptions TableType;
+ bool align_corners = false;
+ bool half_pixel_centers = false;
+};
+
+struct ResizeBilinearOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef ResizeBilinearOptionsT NativeTableType;
+ typedef ResizeBilinearOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_ALIGN_CORNERS = 8,
+ VT_HALF_PIXEL_CENTERS = 10
+ };
+ bool align_corners() const { return GetField<uint8_t>(VT_ALIGN_CORNERS, 0) != 0; }
+ bool half_pixel_centers() const { return GetField<uint8_t>(VT_HALF_PIXEL_CENTERS, 0) != 0; }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<uint8_t>(verifier, VT_ALIGN_CORNERS) &&
+ VerifyField<uint8_t>(verifier, VT_HALF_PIXEL_CENTERS) && verifier.EndTable();
+ }
+ ResizeBilinearOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(ResizeBilinearOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<ResizeBilinearOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const ResizeBilinearOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct ResizeBilinearOptionsBuilder
+{
+ typedef ResizeBilinearOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_align_corners(bool align_corners)
+ {
+ fbb_.AddElement<uint8_t>(ResizeBilinearOptions::VT_ALIGN_CORNERS,
+ static_cast<uint8_t>(align_corners), 0);
+ }
+ void add_half_pixel_centers(bool half_pixel_centers)
+ {
+ fbb_.AddElement<uint8_t>(ResizeBilinearOptions::VT_HALF_PIXEL_CENTERS,
+ static_cast<uint8_t>(half_pixel_centers), 0);
+ }
+ explicit ResizeBilinearOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<ResizeBilinearOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<ResizeBilinearOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<ResizeBilinearOptions>
+CreateResizeBilinearOptions(flatbuffers::FlatBufferBuilder &_fbb, bool align_corners = false,
+ bool half_pixel_centers = false)
+{
+ ResizeBilinearOptionsBuilder builder_(_fbb);
+ builder_.add_half_pixel_centers(half_pixel_centers);
+ builder_.add_align_corners(align_corners);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<ResizeBilinearOptions>
+CreateResizeBilinearOptions(flatbuffers::FlatBufferBuilder &_fbb, const ResizeBilinearOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct ResizeNearestNeighborOptionsT : public flatbuffers::NativeTable
+{
+ typedef ResizeNearestNeighborOptions TableType;
+ bool align_corners = false;
+ bool half_pixel_centers = false;
+};
+
+struct ResizeNearestNeighborOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef ResizeNearestNeighborOptionsT NativeTableType;
+ typedef ResizeNearestNeighborOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_ALIGN_CORNERS = 4,
+ VT_HALF_PIXEL_CENTERS = 6
+ };
+ bool align_corners() const { return GetField<uint8_t>(VT_ALIGN_CORNERS, 0) != 0; }
+ bool half_pixel_centers() const { return GetField<uint8_t>(VT_HALF_PIXEL_CENTERS, 0) != 0; }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<uint8_t>(verifier, VT_ALIGN_CORNERS) &&
+ VerifyField<uint8_t>(verifier, VT_HALF_PIXEL_CENTERS) && verifier.EndTable();
+ }
+ ResizeNearestNeighborOptionsT *
+ UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(ResizeNearestNeighborOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<ResizeNearestNeighborOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const ResizeNearestNeighborOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct ResizeNearestNeighborOptionsBuilder
+{
+ typedef ResizeNearestNeighborOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_align_corners(bool align_corners)
+ {
+ fbb_.AddElement<uint8_t>(ResizeNearestNeighborOptions::VT_ALIGN_CORNERS,
+ static_cast<uint8_t>(align_corners), 0);
+ }
+ void add_half_pixel_centers(bool half_pixel_centers)
+ {
+ fbb_.AddElement<uint8_t>(ResizeNearestNeighborOptions::VT_HALF_PIXEL_CENTERS,
+ static_cast<uint8_t>(half_pixel_centers), 0);
+ }
+ explicit ResizeNearestNeighborOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<ResizeNearestNeighborOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<ResizeNearestNeighborOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<ResizeNearestNeighborOptions>
+CreateResizeNearestNeighborOptions(flatbuffers::FlatBufferBuilder &_fbb, bool align_corners = false,
+ bool half_pixel_centers = false)
+{
+ ResizeNearestNeighborOptionsBuilder builder_(_fbb);
+ builder_.add_half_pixel_centers(half_pixel_centers);
+ builder_.add_align_corners(align_corners);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<ResizeNearestNeighborOptions>
+CreateResizeNearestNeighborOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ const ResizeNearestNeighborOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct CallOptionsT : public flatbuffers::NativeTable
+{
+ typedef CallOptions TableType;
+ uint32_t subgraph = 0;
+};
+
+struct CallOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef CallOptionsT NativeTableType;
+ typedef CallOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_SUBGRAPH = 4
+ };
+ uint32_t subgraph() const { return GetField<uint32_t>(VT_SUBGRAPH, 0); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<uint32_t>(verifier, VT_SUBGRAPH) &&
+ verifier.EndTable();
+ }
+ CallOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(CallOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<CallOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const CallOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct CallOptionsBuilder
+{
+ typedef CallOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_subgraph(uint32_t subgraph)
+ {
+ fbb_.AddElement<uint32_t>(CallOptions::VT_SUBGRAPH, subgraph, 0);
+ }
+ explicit CallOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<CallOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<CallOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<CallOptions> CreateCallOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ uint32_t subgraph = 0)
+{
+ CallOptionsBuilder builder_(_fbb);
+ builder_.add_subgraph(subgraph);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<CallOptions>
+CreateCallOptions(flatbuffers::FlatBufferBuilder &_fbb, const CallOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct PadOptionsT : public flatbuffers::NativeTable
+{
+ typedef PadOptions TableType;
+};
+
+struct PadOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef PadOptionsT NativeTableType;
+ typedef PadOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ PadOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(PadOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<PadOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const PadOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct PadOptionsBuilder
+{
+ typedef PadOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit PadOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<PadOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<PadOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<PadOptions> CreatePadOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ PadOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<PadOptions>
+CreatePadOptions(flatbuffers::FlatBufferBuilder &_fbb, const PadOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct PadV2OptionsT : public flatbuffers::NativeTable
+{
+ typedef PadV2Options TableType;
+};
+
+struct PadV2Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef PadV2OptionsT NativeTableType;
+ typedef PadV2OptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ PadV2OptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(PadV2OptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<PadV2Options>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const PadV2OptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct PadV2OptionsBuilder
+{
+ typedef PadV2Options Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit PadV2OptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<PadV2Options> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<PadV2Options>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<PadV2Options> CreatePadV2Options(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ PadV2OptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<PadV2Options>
+CreatePadV2Options(flatbuffers::FlatBufferBuilder &_fbb, const PadV2OptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct ReshapeOptionsT : public flatbuffers::NativeTable
+{
+ typedef ReshapeOptions TableType;
+ std::vector<int32_t> new_shape{};
+};
+
+struct ReshapeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef ReshapeOptionsT NativeTableType;
+ typedef ReshapeOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_NEW_SHAPE = 4
+ };
+ const flatbuffers::Vector<int32_t> *new_shape() const
+ {
+ return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_NEW_SHAPE);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_NEW_SHAPE) &&
+ verifier.VerifyVector(new_shape()) && verifier.EndTable();
+ }
+ ReshapeOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(ReshapeOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<ReshapeOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const ReshapeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct ReshapeOptionsBuilder
+{
+ typedef ReshapeOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_new_shape(flatbuffers::Offset<flatbuffers::Vector<int32_t>> new_shape)
+ {
+ fbb_.AddOffset(ReshapeOptions::VT_NEW_SHAPE, new_shape);
+ }
+ explicit ReshapeOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<ReshapeOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<ReshapeOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<ReshapeOptions>
+CreateReshapeOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::Vector<int32_t>> new_shape = 0)
+{
+ ReshapeOptionsBuilder builder_(_fbb);
+ builder_.add_new_shape(new_shape);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<ReshapeOptions>
+CreateReshapeOptionsDirect(flatbuffers::FlatBufferBuilder &_fbb,
+ const std::vector<int32_t> *new_shape = nullptr)
+{
+ auto new_shape__ = new_shape ? _fbb.CreateVector<int32_t>(*new_shape) : 0;
+ return circle::CreateReshapeOptions(_fbb, new_shape__);
+}
+
+flatbuffers::Offset<ReshapeOptions>
+CreateReshapeOptions(flatbuffers::FlatBufferBuilder &_fbb, const ReshapeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct SpaceToBatchNDOptionsT : public flatbuffers::NativeTable
+{
+ typedef SpaceToBatchNDOptions TableType;
+};
+
+struct SpaceToBatchNDOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef SpaceToBatchNDOptionsT NativeTableType;
+ typedef SpaceToBatchNDOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ SpaceToBatchNDOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(SpaceToBatchNDOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<SpaceToBatchNDOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const SpaceToBatchNDOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct SpaceToBatchNDOptionsBuilder
+{
+ typedef SpaceToBatchNDOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit SpaceToBatchNDOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<SpaceToBatchNDOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<SpaceToBatchNDOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<SpaceToBatchNDOptions>
+CreateSpaceToBatchNDOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ SpaceToBatchNDOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<SpaceToBatchNDOptions>
+CreateSpaceToBatchNDOptions(flatbuffers::FlatBufferBuilder &_fbb, const SpaceToBatchNDOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct BatchToSpaceNDOptionsT : public flatbuffers::NativeTable
+{
+ typedef BatchToSpaceNDOptions TableType;
+};
+
+struct BatchToSpaceNDOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef BatchToSpaceNDOptionsT NativeTableType;
+ typedef BatchToSpaceNDOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ BatchToSpaceNDOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(BatchToSpaceNDOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<BatchToSpaceNDOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const BatchToSpaceNDOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct BatchToSpaceNDOptionsBuilder
+{
+ typedef BatchToSpaceNDOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit BatchToSpaceNDOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<BatchToSpaceNDOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<BatchToSpaceNDOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<BatchToSpaceNDOptions>
+CreateBatchToSpaceNDOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ BatchToSpaceNDOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<BatchToSpaceNDOptions>
+CreateBatchToSpaceNDOptions(flatbuffers::FlatBufferBuilder &_fbb, const BatchToSpaceNDOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct SkipGramOptionsT : public flatbuffers::NativeTable
+{
+ typedef SkipGramOptions TableType;
+ int32_t ngram_size = 0;
+ int32_t max_skip_size = 0;
+ bool include_all_ngrams = false;
+};
+
+struct SkipGramOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef SkipGramOptionsT NativeTableType;
+ typedef SkipGramOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_NGRAM_SIZE = 4,
+ VT_MAX_SKIP_SIZE = 6,
+ VT_INCLUDE_ALL_NGRAMS = 8
+ };
+ int32_t ngram_size() const { return GetField<int32_t>(VT_NGRAM_SIZE, 0); }
+ int32_t max_skip_size() const { return GetField<int32_t>(VT_MAX_SKIP_SIZE, 0); }
+ bool include_all_ngrams() const { return GetField<uint8_t>(VT_INCLUDE_ALL_NGRAMS, 0) != 0; }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_NGRAM_SIZE) &&
+ VerifyField<int32_t>(verifier, VT_MAX_SKIP_SIZE) &&
+ VerifyField<uint8_t>(verifier, VT_INCLUDE_ALL_NGRAMS) && verifier.EndTable();
+ }
+ SkipGramOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(SkipGramOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<SkipGramOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const SkipGramOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct SkipGramOptionsBuilder
+{
+ typedef SkipGramOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_ngram_size(int32_t ngram_size)
+ {
+ fbb_.AddElement<int32_t>(SkipGramOptions::VT_NGRAM_SIZE, ngram_size, 0);
+ }
+ void add_max_skip_size(int32_t max_skip_size)
+ {
+ fbb_.AddElement<int32_t>(SkipGramOptions::VT_MAX_SKIP_SIZE, max_skip_size, 0);
+ }
+ void add_include_all_ngrams(bool include_all_ngrams)
+ {
+ fbb_.AddElement<uint8_t>(SkipGramOptions::VT_INCLUDE_ALL_NGRAMS,
+ static_cast<uint8_t>(include_all_ngrams), 0);
+ }
+ explicit SkipGramOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<SkipGramOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<SkipGramOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<SkipGramOptions>
+CreateSkipGramOptions(flatbuffers::FlatBufferBuilder &_fbb, int32_t ngram_size = 0,
+ int32_t max_skip_size = 0, bool include_all_ngrams = false)
+{
+ SkipGramOptionsBuilder builder_(_fbb);
+ builder_.add_max_skip_size(max_skip_size);
+ builder_.add_ngram_size(ngram_size);
+ builder_.add_include_all_ngrams(include_all_ngrams);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<SkipGramOptions>
+CreateSkipGramOptions(flatbuffers::FlatBufferBuilder &_fbb, const SkipGramOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct SpaceToDepthOptionsT : public flatbuffers::NativeTable
+{
+ typedef SpaceToDepthOptions TableType;
+ int32_t block_size = 0;
+};
+
+struct SpaceToDepthOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef SpaceToDepthOptionsT NativeTableType;
+ typedef SpaceToDepthOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_BLOCK_SIZE = 4
+ };
+ int32_t block_size() const { return GetField<int32_t>(VT_BLOCK_SIZE, 0); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_BLOCK_SIZE) &&
+ verifier.EndTable();
+ }
+ SpaceToDepthOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(SpaceToDepthOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<SpaceToDepthOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const SpaceToDepthOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct SpaceToDepthOptionsBuilder
+{
+ typedef SpaceToDepthOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_block_size(int32_t block_size)
+ {
+ fbb_.AddElement<int32_t>(SpaceToDepthOptions::VT_BLOCK_SIZE, block_size, 0);
+ }
+ explicit SpaceToDepthOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<SpaceToDepthOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<SpaceToDepthOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<SpaceToDepthOptions>
+CreateSpaceToDepthOptions(flatbuffers::FlatBufferBuilder &_fbb, int32_t block_size = 0)
+{
+ SpaceToDepthOptionsBuilder builder_(_fbb);
+ builder_.add_block_size(block_size);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<SpaceToDepthOptions>
+CreateSpaceToDepthOptions(flatbuffers::FlatBufferBuilder &_fbb, const SpaceToDepthOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct DepthToSpaceOptionsT : public flatbuffers::NativeTable
+{
+ typedef DepthToSpaceOptions TableType;
+ int32_t block_size = 0;
+};
+
+struct DepthToSpaceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef DepthToSpaceOptionsT NativeTableType;
+ typedef DepthToSpaceOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_BLOCK_SIZE = 4
+ };
+ int32_t block_size() const { return GetField<int32_t>(VT_BLOCK_SIZE, 0); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_BLOCK_SIZE) &&
+ verifier.EndTable();
+ }
+ DepthToSpaceOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(DepthToSpaceOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<DepthToSpaceOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const DepthToSpaceOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct DepthToSpaceOptionsBuilder
+{
+ typedef DepthToSpaceOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_block_size(int32_t block_size)
+ {
+ fbb_.AddElement<int32_t>(DepthToSpaceOptions::VT_BLOCK_SIZE, block_size, 0);
+ }
+ explicit DepthToSpaceOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<DepthToSpaceOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<DepthToSpaceOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<DepthToSpaceOptions>
+CreateDepthToSpaceOptions(flatbuffers::FlatBufferBuilder &_fbb, int32_t block_size = 0)
+{
+ DepthToSpaceOptionsBuilder builder_(_fbb);
+ builder_.add_block_size(block_size);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<DepthToSpaceOptions>
+CreateDepthToSpaceOptions(flatbuffers::FlatBufferBuilder &_fbb, const DepthToSpaceOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct SubOptionsT : public flatbuffers::NativeTable
+{
+ typedef SubOptions TableType;
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
+ bool pot_scale_int16 = true;
+};
+
+struct SubOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef SubOptionsT NativeTableType;
+ typedef SubOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_FUSED_ACTIVATION_FUNCTION = 4,
+ VT_POT_SCALE_INT16 = 6
+ };
+ circle::ActivationFunctionType fused_activation_function() const
+ {
+ return static_cast<circle::ActivationFunctionType>(
+ GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+ }
+ bool pot_scale_int16() const { return GetField<uint8_t>(VT_POT_SCALE_INT16, 1) != 0; }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) &&
+ VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION) &&
+ VerifyField<uint8_t>(verifier, VT_POT_SCALE_INT16) && verifier.EndTable();
+ }
+ SubOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(SubOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<SubOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const SubOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct SubOptionsBuilder
+{
+ typedef SubOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_fused_activation_function(circle::ActivationFunctionType fused_activation_function)
+ {
+ fbb_.AddElement<int8_t>(SubOptions::VT_FUSED_ACTIVATION_FUNCTION,
+ static_cast<int8_t>(fused_activation_function), 0);
+ }
+ void add_pot_scale_int16(bool pot_scale_int16)
+ {
+ fbb_.AddElement<uint8_t>(SubOptions::VT_POT_SCALE_INT16, static_cast<uint8_t>(pot_scale_int16),
+ 1);
+ }
+ explicit SubOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<SubOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<SubOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<SubOptions> CreateSubOptions(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE,
+ bool pot_scale_int16 = true)
+{
+ SubOptionsBuilder builder_(_fbb);
+ builder_.add_pot_scale_int16(pot_scale_int16);
+ builder_.add_fused_activation_function(fused_activation_function);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<SubOptions>
+CreateSubOptions(flatbuffers::FlatBufferBuilder &_fbb, const SubOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct DivOptionsT : public flatbuffers::NativeTable
+{
+ typedef DivOptions TableType;
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
+};
+
+struct DivOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef DivOptionsT NativeTableType;
+ typedef DivOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_FUSED_ACTIVATION_FUNCTION = 4
+ };
+ circle::ActivationFunctionType fused_activation_function() const
+ {
+ return static_cast<circle::ActivationFunctionType>(
+ GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) &&
+ VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION) && verifier.EndTable();
+ }
+ DivOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(DivOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<DivOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const DivOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct DivOptionsBuilder
+{
+ typedef DivOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_fused_activation_function(circle::ActivationFunctionType fused_activation_function)
+ {
+ fbb_.AddElement<int8_t>(DivOptions::VT_FUSED_ACTIVATION_FUNCTION,
+ static_cast<int8_t>(fused_activation_function), 0);
+ }
+ explicit DivOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<DivOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<DivOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<DivOptions> CreateDivOptions(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE)
+{
+ DivOptionsBuilder builder_(_fbb);
+ builder_.add_fused_activation_function(fused_activation_function);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<DivOptions>
+CreateDivOptions(flatbuffers::FlatBufferBuilder &_fbb, const DivOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct TopKV2OptionsT : public flatbuffers::NativeTable
+{
+ typedef TopKV2Options TableType;
+};
+
+struct TopKV2Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef TopKV2OptionsT NativeTableType;
+ typedef TopKV2OptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ TopKV2OptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(TopKV2OptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<TopKV2Options>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const TopKV2OptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct TopKV2OptionsBuilder
+{
+ typedef TopKV2Options Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit TopKV2OptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<TopKV2Options> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<TopKV2Options>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<TopKV2Options> CreateTopKV2Options(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ TopKV2OptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<TopKV2Options>
+CreateTopKV2Options(flatbuffers::FlatBufferBuilder &_fbb, const TopKV2OptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct EmbeddingLookupSparseOptionsT : public flatbuffers::NativeTable
+{
+ typedef EmbeddingLookupSparseOptions TableType;
+ circle::CombinerType combiner = circle::CombinerType_SUM;
+};
+
+struct EmbeddingLookupSparseOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef EmbeddingLookupSparseOptionsT NativeTableType;
+ typedef EmbeddingLookupSparseOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_COMBINER = 4
+ };
+ circle::CombinerType combiner() const
+ {
+ return static_cast<circle::CombinerType>(GetField<int8_t>(VT_COMBINER, 0));
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_COMBINER) &&
+ verifier.EndTable();
+ }
+ EmbeddingLookupSparseOptionsT *
+ UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(EmbeddingLookupSparseOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<EmbeddingLookupSparseOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const EmbeddingLookupSparseOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct EmbeddingLookupSparseOptionsBuilder
+{
+ typedef EmbeddingLookupSparseOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_combiner(circle::CombinerType combiner)
+ {
+ fbb_.AddElement<int8_t>(EmbeddingLookupSparseOptions::VT_COMBINER,
+ static_cast<int8_t>(combiner), 0);
+ }
+ explicit EmbeddingLookupSparseOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<EmbeddingLookupSparseOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<EmbeddingLookupSparseOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<EmbeddingLookupSparseOptions>
+CreateEmbeddingLookupSparseOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ circle::CombinerType combiner = circle::CombinerType_SUM)
+{
+ EmbeddingLookupSparseOptionsBuilder builder_(_fbb);
+ builder_.add_combiner(combiner);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<EmbeddingLookupSparseOptions>
+CreateEmbeddingLookupSparseOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ const EmbeddingLookupSparseOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct GatherOptionsT : public flatbuffers::NativeTable
+{
+ typedef GatherOptions TableType;
+ int32_t axis = 0;
+ int32_t batch_dims = 0;
+};
+
+struct GatherOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef GatherOptionsT NativeTableType;
+ typedef GatherOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_AXIS = 4,
+ VT_BATCH_DIMS = 6
+ };
+ int32_t axis() const { return GetField<int32_t>(VT_AXIS, 0); }
+ int32_t batch_dims() const { return GetField<int32_t>(VT_BATCH_DIMS, 0); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_AXIS) &&
+ VerifyField<int32_t>(verifier, VT_BATCH_DIMS) && verifier.EndTable();
+ }
+ GatherOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(GatherOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<GatherOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const GatherOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct GatherOptionsBuilder
+{
+ typedef GatherOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_axis(int32_t axis) { fbb_.AddElement<int32_t>(GatherOptions::VT_AXIS, axis, 0); }
+ void add_batch_dims(int32_t batch_dims)
+ {
+ fbb_.AddElement<int32_t>(GatherOptions::VT_BATCH_DIMS, batch_dims, 0);
+ }
+ explicit GatherOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<GatherOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<GatherOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<GatherOptions>
+CreateGatherOptions(flatbuffers::FlatBufferBuilder &_fbb, int32_t axis = 0, int32_t batch_dims = 0)
+{
+ GatherOptionsBuilder builder_(_fbb);
+ builder_.add_batch_dims(batch_dims);
+ builder_.add_axis(axis);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<GatherOptions>
+CreateGatherOptions(flatbuffers::FlatBufferBuilder &_fbb, const GatherOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct TransposeOptionsT : public flatbuffers::NativeTable
+{
+ typedef TransposeOptions TableType;
+};
+
+struct TransposeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef TransposeOptionsT NativeTableType;
+ typedef TransposeOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ TransposeOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(TransposeOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<TransposeOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const TransposeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct TransposeOptionsBuilder
+{
+ typedef TransposeOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit TransposeOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<TransposeOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<TransposeOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<TransposeOptions>
+CreateTransposeOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ TransposeOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<TransposeOptions>
+CreateTransposeOptions(flatbuffers::FlatBufferBuilder &_fbb, const TransposeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct ExpOptionsT : public flatbuffers::NativeTable
+{
+ typedef ExpOptions TableType;
+};
+
+struct ExpOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef ExpOptionsT NativeTableType;
+ typedef ExpOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ ExpOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(ExpOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<ExpOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const ExpOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct ExpOptionsBuilder
+{
+ typedef ExpOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit ExpOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<ExpOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<ExpOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<ExpOptions> CreateExpOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ ExpOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<ExpOptions>
+CreateExpOptions(flatbuffers::FlatBufferBuilder &_fbb, const ExpOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct CosOptionsT : public flatbuffers::NativeTable
+{
+ typedef CosOptions TableType;
+};
+
+struct CosOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef CosOptionsT NativeTableType;
+ typedef CosOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ CosOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(CosOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<CosOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const CosOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct CosOptionsBuilder
+{
+ typedef CosOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit CosOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<CosOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<CosOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<CosOptions> CreateCosOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ CosOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<CosOptions>
+CreateCosOptions(flatbuffers::FlatBufferBuilder &_fbb, const CosOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct ReducerOptionsT : public flatbuffers::NativeTable
+{
+ typedef ReducerOptions TableType;
+ bool keep_dims = false;
+};
+
+struct ReducerOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef ReducerOptionsT NativeTableType;
+ typedef ReducerOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_KEEP_DIMS = 4
+ };
+ bool keep_dims() const { return GetField<uint8_t>(VT_KEEP_DIMS, 0) != 0; }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<uint8_t>(verifier, VT_KEEP_DIMS) &&
+ verifier.EndTable();
+ }
+ ReducerOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(ReducerOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<ReducerOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const ReducerOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct ReducerOptionsBuilder
+{
+ typedef ReducerOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_keep_dims(bool keep_dims)
+ {
+ fbb_.AddElement<uint8_t>(ReducerOptions::VT_KEEP_DIMS, static_cast<uint8_t>(keep_dims), 0);
+ }
+ explicit ReducerOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<ReducerOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<ReducerOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<ReducerOptions>
+CreateReducerOptions(flatbuffers::FlatBufferBuilder &_fbb, bool keep_dims = false)
+{
+ ReducerOptionsBuilder builder_(_fbb);
+ builder_.add_keep_dims(keep_dims);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<ReducerOptions>
+CreateReducerOptions(flatbuffers::FlatBufferBuilder &_fbb, const ReducerOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct SqueezeOptionsT : public flatbuffers::NativeTable
+{
+ typedef SqueezeOptions TableType;
+ std::vector<int32_t> squeeze_dims{};
+};
+
+struct SqueezeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef SqueezeOptionsT NativeTableType;
+ typedef SqueezeOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_SQUEEZE_DIMS = 4
+ };
+ const flatbuffers::Vector<int32_t> *squeeze_dims() const
+ {
+ return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_SQUEEZE_DIMS);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_SQUEEZE_DIMS) &&
+ verifier.VerifyVector(squeeze_dims()) && verifier.EndTable();
+ }
+ SqueezeOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(SqueezeOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<SqueezeOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const SqueezeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct SqueezeOptionsBuilder
+{
+ typedef SqueezeOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_squeeze_dims(flatbuffers::Offset<flatbuffers::Vector<int32_t>> squeeze_dims)
+ {
+ fbb_.AddOffset(SqueezeOptions::VT_SQUEEZE_DIMS, squeeze_dims);
+ }
+ explicit SqueezeOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<SqueezeOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<SqueezeOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<SqueezeOptions>
+CreateSqueezeOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::Vector<int32_t>> squeeze_dims = 0)
+{
+ SqueezeOptionsBuilder builder_(_fbb);
+ builder_.add_squeeze_dims(squeeze_dims);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<SqueezeOptions>
+CreateSqueezeOptionsDirect(flatbuffers::FlatBufferBuilder &_fbb,
+ const std::vector<int32_t> *squeeze_dims = nullptr)
+{
+ auto squeeze_dims__ = squeeze_dims ? _fbb.CreateVector<int32_t>(*squeeze_dims) : 0;
+ return circle::CreateSqueezeOptions(_fbb, squeeze_dims__);
+}
+
+flatbuffers::Offset<SqueezeOptions>
+CreateSqueezeOptions(flatbuffers::FlatBufferBuilder &_fbb, const SqueezeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct SplitOptionsT : public flatbuffers::NativeTable
+{
+ typedef SplitOptions TableType;
+ int32_t num_splits = 0;
+};
+
+struct SplitOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef SplitOptionsT NativeTableType;
+ typedef SplitOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_NUM_SPLITS = 4
+ };
+ int32_t num_splits() const { return GetField<int32_t>(VT_NUM_SPLITS, 0); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_NUM_SPLITS) &&
+ verifier.EndTable();
+ }
+ SplitOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(SplitOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<SplitOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const SplitOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct SplitOptionsBuilder
+{
+ typedef SplitOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_num_splits(int32_t num_splits)
+ {
+ fbb_.AddElement<int32_t>(SplitOptions::VT_NUM_SPLITS, num_splits, 0);
+ }
+ explicit SplitOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<SplitOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<SplitOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<SplitOptions> CreateSplitOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ int32_t num_splits = 0)
+{
+ SplitOptionsBuilder builder_(_fbb);
+ builder_.add_num_splits(num_splits);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<SplitOptions>
+CreateSplitOptions(flatbuffers::FlatBufferBuilder &_fbb, const SplitOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct SplitVOptionsT : public flatbuffers::NativeTable
+{
+ typedef SplitVOptions TableType;
+ int32_t num_splits = 0;
+};
+
+struct SplitVOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef SplitVOptionsT NativeTableType;
+ typedef SplitVOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_NUM_SPLITS = 4
+ };
+ int32_t num_splits() const { return GetField<int32_t>(VT_NUM_SPLITS, 0); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_NUM_SPLITS) &&
+ verifier.EndTable();
+ }
+ SplitVOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(SplitVOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<SplitVOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const SplitVOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct SplitVOptionsBuilder
+{
+ typedef SplitVOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_num_splits(int32_t num_splits)
+ {
+ fbb_.AddElement<int32_t>(SplitVOptions::VT_NUM_SPLITS, num_splits, 0);
+ }
+ explicit SplitVOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<SplitVOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<SplitVOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<SplitVOptions> CreateSplitVOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ int32_t num_splits = 0)
+{
+ SplitVOptionsBuilder builder_(_fbb);
+ builder_.add_num_splits(num_splits);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<SplitVOptions>
+CreateSplitVOptions(flatbuffers::FlatBufferBuilder &_fbb, const SplitVOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct StridedSliceOptionsT : public flatbuffers::NativeTable
+{
+ typedef StridedSliceOptions TableType;
+ int32_t begin_mask = 0;
+ int32_t end_mask = 0;
+ int32_t ellipsis_mask = 0;
+ int32_t new_axis_mask = 0;
+ int32_t shrink_axis_mask = 0;
+};
+
+struct StridedSliceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef StridedSliceOptionsT NativeTableType;
+ typedef StridedSliceOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_BEGIN_MASK = 4,
+ VT_END_MASK = 6,
+ VT_ELLIPSIS_MASK = 8,
+ VT_NEW_AXIS_MASK = 10,
+ VT_SHRINK_AXIS_MASK = 12
+ };
+ int32_t begin_mask() const { return GetField<int32_t>(VT_BEGIN_MASK, 0); }
+ int32_t end_mask() const { return GetField<int32_t>(VT_END_MASK, 0); }
+ int32_t ellipsis_mask() const { return GetField<int32_t>(VT_ELLIPSIS_MASK, 0); }
+ int32_t new_axis_mask() const { return GetField<int32_t>(VT_NEW_AXIS_MASK, 0); }
+ int32_t shrink_axis_mask() const { return GetField<int32_t>(VT_SHRINK_AXIS_MASK, 0); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_BEGIN_MASK) &&
+ VerifyField<int32_t>(verifier, VT_END_MASK) &&
+ VerifyField<int32_t>(verifier, VT_ELLIPSIS_MASK) &&
+ VerifyField<int32_t>(verifier, VT_NEW_AXIS_MASK) &&
+ VerifyField<int32_t>(verifier, VT_SHRINK_AXIS_MASK) && verifier.EndTable();
+ }
+ StridedSliceOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(StridedSliceOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<StridedSliceOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const StridedSliceOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct StridedSliceOptionsBuilder
+{
+ typedef StridedSliceOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_begin_mask(int32_t begin_mask)
+ {
+ fbb_.AddElement<int32_t>(StridedSliceOptions::VT_BEGIN_MASK, begin_mask, 0);
+ }
+ void add_end_mask(int32_t end_mask)
+ {
+ fbb_.AddElement<int32_t>(StridedSliceOptions::VT_END_MASK, end_mask, 0);
+ }
+ void add_ellipsis_mask(int32_t ellipsis_mask)
+ {
+ fbb_.AddElement<int32_t>(StridedSliceOptions::VT_ELLIPSIS_MASK, ellipsis_mask, 0);
+ }
+ void add_new_axis_mask(int32_t new_axis_mask)
+ {
+ fbb_.AddElement<int32_t>(StridedSliceOptions::VT_NEW_AXIS_MASK, new_axis_mask, 0);
+ }
+ void add_shrink_axis_mask(int32_t shrink_axis_mask)
+ {
+ fbb_.AddElement<int32_t>(StridedSliceOptions::VT_SHRINK_AXIS_MASK, shrink_axis_mask, 0);
+ }
+ explicit StridedSliceOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<StridedSliceOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<StridedSliceOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<StridedSliceOptions>
+CreateStridedSliceOptions(flatbuffers::FlatBufferBuilder &_fbb, int32_t begin_mask = 0,
+ int32_t end_mask = 0, int32_t ellipsis_mask = 0,
+ int32_t new_axis_mask = 0, int32_t shrink_axis_mask = 0)
+{
+ StridedSliceOptionsBuilder builder_(_fbb);
+ builder_.add_shrink_axis_mask(shrink_axis_mask);
+ builder_.add_new_axis_mask(new_axis_mask);
+ builder_.add_ellipsis_mask(ellipsis_mask);
+ builder_.add_end_mask(end_mask);
+ builder_.add_begin_mask(begin_mask);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<StridedSliceOptions>
+CreateStridedSliceOptions(flatbuffers::FlatBufferBuilder &_fbb, const StridedSliceOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct LogSoftmaxOptionsT : public flatbuffers::NativeTable
+{
+ typedef LogSoftmaxOptions TableType;
+};
+
+struct LogSoftmaxOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef LogSoftmaxOptionsT NativeTableType;
+ typedef LogSoftmaxOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ LogSoftmaxOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(LogSoftmaxOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<LogSoftmaxOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const LogSoftmaxOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct LogSoftmaxOptionsBuilder
+{
+ typedef LogSoftmaxOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit LogSoftmaxOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<LogSoftmaxOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<LogSoftmaxOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<LogSoftmaxOptions>
+CreateLogSoftmaxOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ LogSoftmaxOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<LogSoftmaxOptions>
+CreateLogSoftmaxOptions(flatbuffers::FlatBufferBuilder &_fbb, const LogSoftmaxOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct CastOptionsT : public flatbuffers::NativeTable
+{
+ typedef CastOptions TableType;
+ circle::TensorType in_data_type = circle::TensorType_FLOAT32;
+ circle::TensorType out_data_type = circle::TensorType_FLOAT32;
+};
+
+struct CastOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef CastOptionsT NativeTableType;
+ typedef CastOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_IN_DATA_TYPE = 4,
+ VT_OUT_DATA_TYPE = 6
+ };
+ circle::TensorType in_data_type() const
+ {
+ return static_cast<circle::TensorType>(GetField<int8_t>(VT_IN_DATA_TYPE, 0));
+ }
+ circle::TensorType out_data_type() const
+ {
+ return static_cast<circle::TensorType>(GetField<int8_t>(VT_OUT_DATA_TYPE, 0));
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_IN_DATA_TYPE) &&
+ VerifyField<int8_t>(verifier, VT_OUT_DATA_TYPE) && verifier.EndTable();
+ }
+ CastOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(CastOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<CastOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const CastOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct CastOptionsBuilder
+{
+ typedef CastOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_in_data_type(circle::TensorType in_data_type)
+ {
+ fbb_.AddElement<int8_t>(CastOptions::VT_IN_DATA_TYPE, static_cast<int8_t>(in_data_type), 0);
+ }
+ void add_out_data_type(circle::TensorType out_data_type)
+ {
+ fbb_.AddElement<int8_t>(CastOptions::VT_OUT_DATA_TYPE, static_cast<int8_t>(out_data_type), 0);
+ }
+ explicit CastOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<CastOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<CastOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<CastOptions>
+CreateCastOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ circle::TensorType in_data_type = circle::TensorType_FLOAT32,
+ circle::TensorType out_data_type = circle::TensorType_FLOAT32)
+{
+ CastOptionsBuilder builder_(_fbb);
+ builder_.add_out_data_type(out_data_type);
+ builder_.add_in_data_type(in_data_type);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<CastOptions>
+CreateCastOptions(flatbuffers::FlatBufferBuilder &_fbb, const CastOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct DequantizeOptionsT : public flatbuffers::NativeTable
+{
+ typedef DequantizeOptions TableType;
+};
+
+struct DequantizeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef DequantizeOptionsT NativeTableType;
+ typedef DequantizeOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ DequantizeOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(DequantizeOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<DequantizeOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const DequantizeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct DequantizeOptionsBuilder
+{
+ typedef DequantizeOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit DequantizeOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<DequantizeOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<DequantizeOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<DequantizeOptions>
+CreateDequantizeOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ DequantizeOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<DequantizeOptions>
+CreateDequantizeOptions(flatbuffers::FlatBufferBuilder &_fbb, const DequantizeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct MaximumMinimumOptionsT : public flatbuffers::NativeTable
+{
+ typedef MaximumMinimumOptions TableType;
+};
+
+struct MaximumMinimumOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef MaximumMinimumOptionsT NativeTableType;
+ typedef MaximumMinimumOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ MaximumMinimumOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(MaximumMinimumOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<MaximumMinimumOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const MaximumMinimumOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct MaximumMinimumOptionsBuilder
+{
+ typedef MaximumMinimumOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit MaximumMinimumOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<MaximumMinimumOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<MaximumMinimumOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<MaximumMinimumOptions>
+CreateMaximumMinimumOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ MaximumMinimumOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<MaximumMinimumOptions>
+CreateMaximumMinimumOptions(flatbuffers::FlatBufferBuilder &_fbb, const MaximumMinimumOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct TileOptionsT : public flatbuffers::NativeTable
+{
+ typedef TileOptions TableType;
+};
+
+struct TileOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef TileOptionsT NativeTableType;
+ typedef TileOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ TileOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(TileOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<TileOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const TileOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct TileOptionsBuilder
+{
+ typedef TileOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit TileOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<TileOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<TileOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<TileOptions> CreateTileOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ TileOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<TileOptions>
+CreateTileOptions(flatbuffers::FlatBufferBuilder &_fbb, const TileOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct ArgMaxOptionsT : public flatbuffers::NativeTable
+{
+ typedef ArgMaxOptions TableType;
+ circle::TensorType output_type = circle::TensorType_FLOAT32;
+};
+
+struct ArgMaxOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef ArgMaxOptionsT NativeTableType;
+ typedef ArgMaxOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_OUTPUT_TYPE = 4
+ };
+ circle::TensorType output_type() const
+ {
+ return static_cast<circle::TensorType>(GetField<int8_t>(VT_OUTPUT_TYPE, 0));
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_OUTPUT_TYPE) &&
+ verifier.EndTable();
+ }
+ ArgMaxOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(ArgMaxOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<ArgMaxOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const ArgMaxOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct ArgMaxOptionsBuilder
+{
+ typedef ArgMaxOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_output_type(circle::TensorType output_type)
+ {
+ fbb_.AddElement<int8_t>(ArgMaxOptions::VT_OUTPUT_TYPE, static_cast<int8_t>(output_type), 0);
+ }
+ explicit ArgMaxOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<ArgMaxOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<ArgMaxOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<ArgMaxOptions>
+CreateArgMaxOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ circle::TensorType output_type = circle::TensorType_FLOAT32)
+{
+ ArgMaxOptionsBuilder builder_(_fbb);
+ builder_.add_output_type(output_type);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<ArgMaxOptions>
+CreateArgMaxOptions(flatbuffers::FlatBufferBuilder &_fbb, const ArgMaxOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct ArgMinOptionsT : public flatbuffers::NativeTable
+{
+ typedef ArgMinOptions TableType;
+ circle::TensorType output_type = circle::TensorType_FLOAT32;
+};
+
+struct ArgMinOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef ArgMinOptionsT NativeTableType;
+ typedef ArgMinOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_OUTPUT_TYPE = 4
+ };
+ circle::TensorType output_type() const
+ {
+ return static_cast<circle::TensorType>(GetField<int8_t>(VT_OUTPUT_TYPE, 0));
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_OUTPUT_TYPE) &&
+ verifier.EndTable();
+ }
+ ArgMinOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(ArgMinOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<ArgMinOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const ArgMinOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct ArgMinOptionsBuilder
+{
+ typedef ArgMinOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_output_type(circle::TensorType output_type)
+ {
+ fbb_.AddElement<int8_t>(ArgMinOptions::VT_OUTPUT_TYPE, static_cast<int8_t>(output_type), 0);
+ }
+ explicit ArgMinOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<ArgMinOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<ArgMinOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<ArgMinOptions>
+CreateArgMinOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ circle::TensorType output_type = circle::TensorType_FLOAT32)
+{
+ ArgMinOptionsBuilder builder_(_fbb);
+ builder_.add_output_type(output_type);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<ArgMinOptions>
+CreateArgMinOptions(flatbuffers::FlatBufferBuilder &_fbb, const ArgMinOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct GreaterOptionsT : public flatbuffers::NativeTable
+{
+ typedef GreaterOptions TableType;
+};
+
+struct GreaterOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef GreaterOptionsT NativeTableType;
+ typedef GreaterOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ GreaterOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(GreaterOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<GreaterOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const GreaterOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct GreaterOptionsBuilder
+{
+ typedef GreaterOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit GreaterOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<GreaterOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<GreaterOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<GreaterOptions>
+CreateGreaterOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ GreaterOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<GreaterOptions>
+CreateGreaterOptions(flatbuffers::FlatBufferBuilder &_fbb, const GreaterOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct GreaterEqualOptionsT : public flatbuffers::NativeTable
+{
+ typedef GreaterEqualOptions TableType;
+};
+
+struct GreaterEqualOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef GreaterEqualOptionsT NativeTableType;
+ typedef GreaterEqualOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ GreaterEqualOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(GreaterEqualOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<GreaterEqualOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const GreaterEqualOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct GreaterEqualOptionsBuilder
+{
+ typedef GreaterEqualOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit GreaterEqualOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<GreaterEqualOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<GreaterEqualOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<GreaterEqualOptions>
+CreateGreaterEqualOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ GreaterEqualOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<GreaterEqualOptions>
+CreateGreaterEqualOptions(flatbuffers::FlatBufferBuilder &_fbb, const GreaterEqualOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct LessOptionsT : public flatbuffers::NativeTable
+{
+ typedef LessOptions TableType;
+};
+
+struct LessOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef LessOptionsT NativeTableType;
+ typedef LessOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ LessOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(LessOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<LessOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const LessOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct LessOptionsBuilder
+{
+ typedef LessOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit LessOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<LessOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<LessOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<LessOptions> CreateLessOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ LessOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<LessOptions>
+CreateLessOptions(flatbuffers::FlatBufferBuilder &_fbb, const LessOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct LessEqualOptionsT : public flatbuffers::NativeTable
+{
+ typedef LessEqualOptions TableType;
+};
+
+struct LessEqualOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef LessEqualOptionsT NativeTableType;
+ typedef LessEqualOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ LessEqualOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(LessEqualOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<LessEqualOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const LessEqualOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct LessEqualOptionsBuilder
+{
+ typedef LessEqualOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit LessEqualOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<LessEqualOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<LessEqualOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<LessEqualOptions>
+CreateLessEqualOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ LessEqualOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<LessEqualOptions>
+CreateLessEqualOptions(flatbuffers::FlatBufferBuilder &_fbb, const LessEqualOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct NegOptionsT : public flatbuffers::NativeTable
+{
+ typedef NegOptions TableType;
+};
+
+struct NegOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef NegOptionsT NativeTableType;
+ typedef NegOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ NegOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(NegOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<NegOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const NegOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct NegOptionsBuilder
+{
+ typedef NegOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit NegOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<NegOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<NegOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<NegOptions> CreateNegOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ NegOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<NegOptions>
+CreateNegOptions(flatbuffers::FlatBufferBuilder &_fbb, const NegOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct SelectOptionsT : public flatbuffers::NativeTable
+{
+ typedef SelectOptions TableType;
+};
+
+struct SelectOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef SelectOptionsT NativeTableType;
+ typedef SelectOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ SelectOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(SelectOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<SelectOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const SelectOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct SelectOptionsBuilder
+{
+ typedef SelectOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit SelectOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<SelectOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<SelectOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<SelectOptions> CreateSelectOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ SelectOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<SelectOptions>
+CreateSelectOptions(flatbuffers::FlatBufferBuilder &_fbb, const SelectOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct SliceOptionsT : public flatbuffers::NativeTable
+{
+ typedef SliceOptions TableType;
+};
+
+struct SliceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef SliceOptionsT NativeTableType;
+ typedef SliceOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ SliceOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(SliceOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<SliceOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const SliceOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct SliceOptionsBuilder
+{
+ typedef SliceOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit SliceOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<SliceOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<SliceOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<SliceOptions> CreateSliceOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ SliceOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<SliceOptions>
+CreateSliceOptions(flatbuffers::FlatBufferBuilder &_fbb, const SliceOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct TransposeConvOptionsT : public flatbuffers::NativeTable
+{
+ typedef TransposeConvOptions TableType;
+ circle::Padding padding = circle::Padding_SAME;
+ int32_t stride_w = 0;
+ int32_t stride_h = 0;
+};
+
+struct TransposeConvOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef TransposeConvOptionsT NativeTableType;
+ typedef TransposeConvOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_PADDING = 4,
+ VT_STRIDE_W = 6,
+ VT_STRIDE_H = 8
+ };
+ circle::Padding padding() const
+ {
+ return static_cast<circle::Padding>(GetField<int8_t>(VT_PADDING, 0));
+ }
+ int32_t stride_w() const { return GetField<int32_t>(VT_STRIDE_W, 0); }
+ int32_t stride_h() const { return GetField<int32_t>(VT_STRIDE_H, 0); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_PADDING) &&
+ VerifyField<int32_t>(verifier, VT_STRIDE_W) &&
+ VerifyField<int32_t>(verifier, VT_STRIDE_H) && verifier.EndTable();
+ }
+ TransposeConvOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(TransposeConvOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<TransposeConvOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const TransposeConvOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct TransposeConvOptionsBuilder
+{
+ typedef TransposeConvOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_padding(circle::Padding padding)
+ {
+ fbb_.AddElement<int8_t>(TransposeConvOptions::VT_PADDING, static_cast<int8_t>(padding), 0);
+ }
+ void add_stride_w(int32_t stride_w)
+ {
+ fbb_.AddElement<int32_t>(TransposeConvOptions::VT_STRIDE_W, stride_w, 0);
+ }
+ void add_stride_h(int32_t stride_h)
+ {
+ fbb_.AddElement<int32_t>(TransposeConvOptions::VT_STRIDE_H, stride_h, 0);
+ }
+ explicit TransposeConvOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<TransposeConvOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<TransposeConvOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<TransposeConvOptions>
+CreateTransposeConvOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ circle::Padding padding = circle::Padding_SAME, int32_t stride_w = 0,
+ int32_t stride_h = 0)
+{
+ TransposeConvOptionsBuilder builder_(_fbb);
+ builder_.add_stride_h(stride_h);
+ builder_.add_stride_w(stride_w);
+ builder_.add_padding(padding);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<TransposeConvOptions>
+CreateTransposeConvOptions(flatbuffers::FlatBufferBuilder &_fbb, const TransposeConvOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct ExpandDimsOptionsT : public flatbuffers::NativeTable
+{
+ typedef ExpandDimsOptions TableType;
+};
+
+struct ExpandDimsOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef ExpandDimsOptionsT NativeTableType;
+ typedef ExpandDimsOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ ExpandDimsOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(ExpandDimsOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<ExpandDimsOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const ExpandDimsOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct ExpandDimsOptionsBuilder
+{
+ typedef ExpandDimsOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit ExpandDimsOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<ExpandDimsOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<ExpandDimsOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<ExpandDimsOptions>
+CreateExpandDimsOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ ExpandDimsOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<ExpandDimsOptions>
+CreateExpandDimsOptions(flatbuffers::FlatBufferBuilder &_fbb, const ExpandDimsOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct SparseToDenseOptionsT : public flatbuffers::NativeTable
+{
+ typedef SparseToDenseOptions TableType;
+ bool validate_indices = false;
+};
+
+struct SparseToDenseOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef SparseToDenseOptionsT NativeTableType;
+ typedef SparseToDenseOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_VALIDATE_INDICES = 4
+ };
+ bool validate_indices() const { return GetField<uint8_t>(VT_VALIDATE_INDICES, 0) != 0; }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<uint8_t>(verifier, VT_VALIDATE_INDICES) &&
+ verifier.EndTable();
+ }
+ SparseToDenseOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(SparseToDenseOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<SparseToDenseOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const SparseToDenseOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct SparseToDenseOptionsBuilder
+{
+ typedef SparseToDenseOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_validate_indices(bool validate_indices)
+ {
+ fbb_.AddElement<uint8_t>(SparseToDenseOptions::VT_VALIDATE_INDICES,
+ static_cast<uint8_t>(validate_indices), 0);
+ }
+ explicit SparseToDenseOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<SparseToDenseOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<SparseToDenseOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<SparseToDenseOptions>
+CreateSparseToDenseOptions(flatbuffers::FlatBufferBuilder &_fbb, bool validate_indices = false)
+{
+ SparseToDenseOptionsBuilder builder_(_fbb);
+ builder_.add_validate_indices(validate_indices);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<SparseToDenseOptions>
+CreateSparseToDenseOptions(flatbuffers::FlatBufferBuilder &_fbb, const SparseToDenseOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct EqualOptionsT : public flatbuffers::NativeTable
+{
+ typedef EqualOptions TableType;
+};
+
+struct EqualOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef EqualOptionsT NativeTableType;
+ typedef EqualOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ EqualOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(EqualOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<EqualOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const EqualOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct EqualOptionsBuilder
+{
+ typedef EqualOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit EqualOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<EqualOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<EqualOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<EqualOptions> CreateEqualOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ EqualOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<EqualOptions>
+CreateEqualOptions(flatbuffers::FlatBufferBuilder &_fbb, const EqualOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct NotEqualOptionsT : public flatbuffers::NativeTable
+{
+ typedef NotEqualOptions TableType;
+};
+
+struct NotEqualOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef NotEqualOptionsT NativeTableType;
+ typedef NotEqualOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ NotEqualOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(NotEqualOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<NotEqualOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const NotEqualOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct NotEqualOptionsBuilder
+{
+ typedef NotEqualOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit NotEqualOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<NotEqualOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<NotEqualOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<NotEqualOptions>
+CreateNotEqualOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ NotEqualOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<NotEqualOptions>
+CreateNotEqualOptions(flatbuffers::FlatBufferBuilder &_fbb, const NotEqualOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct ShapeOptionsT : public flatbuffers::NativeTable
+{
+ typedef ShapeOptions TableType;
+ circle::TensorType out_type = circle::TensorType_FLOAT32;
+};
+
+struct ShapeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef ShapeOptionsT NativeTableType;
+ typedef ShapeOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_OUT_TYPE = 4
+ };
+ circle::TensorType out_type() const
+ {
+ return static_cast<circle::TensorType>(GetField<int8_t>(VT_OUT_TYPE, 0));
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_OUT_TYPE) &&
+ verifier.EndTable();
+ }
+ ShapeOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(ShapeOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<ShapeOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const ShapeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct ShapeOptionsBuilder
+{
+ typedef ShapeOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_out_type(circle::TensorType out_type)
+ {
+ fbb_.AddElement<int8_t>(ShapeOptions::VT_OUT_TYPE, static_cast<int8_t>(out_type), 0);
+ }
+ explicit ShapeOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<ShapeOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<ShapeOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<ShapeOptions>
+CreateShapeOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ circle::TensorType out_type = circle::TensorType_FLOAT32)
+{
+ ShapeOptionsBuilder builder_(_fbb);
+ builder_.add_out_type(out_type);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<ShapeOptions>
+CreateShapeOptions(flatbuffers::FlatBufferBuilder &_fbb, const ShapeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct RankOptionsT : public flatbuffers::NativeTable
+{
+ typedef RankOptions TableType;
+};
+
+struct RankOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef RankOptionsT NativeTableType;
+ typedef RankOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ RankOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(RankOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<RankOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const RankOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct RankOptionsBuilder
+{
+ typedef RankOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit RankOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<RankOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<RankOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<RankOptions> CreateRankOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ RankOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<RankOptions>
+CreateRankOptions(flatbuffers::FlatBufferBuilder &_fbb, const RankOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct PowOptionsT : public flatbuffers::NativeTable
+{
+ typedef PowOptions TableType;
+};
+
+struct PowOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef PowOptionsT NativeTableType;
+ typedef PowOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ PowOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(PowOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<PowOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const PowOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct PowOptionsBuilder
+{
+ typedef PowOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit PowOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<PowOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<PowOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<PowOptions> CreatePowOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ PowOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<PowOptions>
+CreatePowOptions(flatbuffers::FlatBufferBuilder &_fbb, const PowOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct FakeQuantOptionsT : public flatbuffers::NativeTable
+{
+ typedef FakeQuantOptions TableType;
+ float min = 0.0f;
+ float max = 0.0f;
+ int32_t num_bits = 0;
+ bool narrow_range = false;
+};
+
+struct FakeQuantOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef FakeQuantOptionsT NativeTableType;
+ typedef FakeQuantOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_MIN = 4,
+ VT_MAX = 6,
+ VT_NUM_BITS = 8,
+ VT_NARROW_RANGE = 10
+ };
+ float min() const { return GetField<float>(VT_MIN, 0.0f); }
+ float max() const { return GetField<float>(VT_MAX, 0.0f); }
+ int32_t num_bits() const { return GetField<int32_t>(VT_NUM_BITS, 0); }
+ bool narrow_range() const { return GetField<uint8_t>(VT_NARROW_RANGE, 0) != 0; }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<float>(verifier, VT_MIN) &&
+ VerifyField<float>(verifier, VT_MAX) && VerifyField<int32_t>(verifier, VT_NUM_BITS) &&
+ VerifyField<uint8_t>(verifier, VT_NARROW_RANGE) && verifier.EndTable();
+ }
+ FakeQuantOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(FakeQuantOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<FakeQuantOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const FakeQuantOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct FakeQuantOptionsBuilder
+{
+ typedef FakeQuantOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_min(float min) { fbb_.AddElement<float>(FakeQuantOptions::VT_MIN, min, 0.0f); }
+ void add_max(float max) { fbb_.AddElement<float>(FakeQuantOptions::VT_MAX, max, 0.0f); }
+ void add_num_bits(int32_t num_bits)
+ {
+ fbb_.AddElement<int32_t>(FakeQuantOptions::VT_NUM_BITS, num_bits, 0);
+ }
+ void add_narrow_range(bool narrow_range)
+ {
+ fbb_.AddElement<uint8_t>(FakeQuantOptions::VT_NARROW_RANGE, static_cast<uint8_t>(narrow_range),
+ 0);
+ }
+ explicit FakeQuantOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<FakeQuantOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<FakeQuantOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<FakeQuantOptions>
+CreateFakeQuantOptions(flatbuffers::FlatBufferBuilder &_fbb, float min = 0.0f, float max = 0.0f,
+ int32_t num_bits = 0, bool narrow_range = false)
+{
+ FakeQuantOptionsBuilder builder_(_fbb);
+ builder_.add_num_bits(num_bits);
+ builder_.add_max(max);
+ builder_.add_min(min);
+ builder_.add_narrow_range(narrow_range);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<FakeQuantOptions>
+CreateFakeQuantOptions(flatbuffers::FlatBufferBuilder &_fbb, const FakeQuantOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct PackOptionsT : public flatbuffers::NativeTable
+{
+ typedef PackOptions TableType;
+ int32_t values_count = 0;
+ int32_t axis = 0;
+};
+
+struct PackOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef PackOptionsT NativeTableType;
+ typedef PackOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_VALUES_COUNT = 4,
+ VT_AXIS = 6
+ };
+ int32_t values_count() const { return GetField<int32_t>(VT_VALUES_COUNT, 0); }
+ int32_t axis() const { return GetField<int32_t>(VT_AXIS, 0); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_VALUES_COUNT) &&
+ VerifyField<int32_t>(verifier, VT_AXIS) && verifier.EndTable();
+ }
+ PackOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(PackOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<PackOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const PackOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct PackOptionsBuilder
+{
+ typedef PackOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_values_count(int32_t values_count)
+ {
+ fbb_.AddElement<int32_t>(PackOptions::VT_VALUES_COUNT, values_count, 0);
+ }
+ void add_axis(int32_t axis) { fbb_.AddElement<int32_t>(PackOptions::VT_AXIS, axis, 0); }
+ explicit PackOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<PackOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<PackOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<PackOptions>
+CreatePackOptions(flatbuffers::FlatBufferBuilder &_fbb, int32_t values_count = 0, int32_t axis = 0)
+{
+ PackOptionsBuilder builder_(_fbb);
+ builder_.add_axis(axis);
+ builder_.add_values_count(values_count);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<PackOptions>
+CreatePackOptions(flatbuffers::FlatBufferBuilder &_fbb, const PackOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct LogicalOrOptionsT : public flatbuffers::NativeTable
+{
+ typedef LogicalOrOptions TableType;
+};
+
+struct LogicalOrOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef LogicalOrOptionsT NativeTableType;
+ typedef LogicalOrOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ LogicalOrOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(LogicalOrOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<LogicalOrOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const LogicalOrOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct LogicalOrOptionsBuilder
+{
+ typedef LogicalOrOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit LogicalOrOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<LogicalOrOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<LogicalOrOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<LogicalOrOptions>
+CreateLogicalOrOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ LogicalOrOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<LogicalOrOptions>
+CreateLogicalOrOptions(flatbuffers::FlatBufferBuilder &_fbb, const LogicalOrOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct OneHotOptionsT : public flatbuffers::NativeTable
+{
+ typedef OneHotOptions TableType;
+ int32_t axis = 0;
+};
+
+struct OneHotOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef OneHotOptionsT NativeTableType;
+ typedef OneHotOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_AXIS = 4
+ };
+ int32_t axis() const { return GetField<int32_t>(VT_AXIS, 0); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_AXIS) &&
+ verifier.EndTable();
+ }
+ OneHotOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(OneHotOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<OneHotOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const OneHotOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct OneHotOptionsBuilder
+{
+ typedef OneHotOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_axis(int32_t axis) { fbb_.AddElement<int32_t>(OneHotOptions::VT_AXIS, axis, 0); }
+ explicit OneHotOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<OneHotOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<OneHotOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<OneHotOptions> CreateOneHotOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ int32_t axis = 0)
+{
+ OneHotOptionsBuilder builder_(_fbb);
+ builder_.add_axis(axis);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<OneHotOptions>
+CreateOneHotOptions(flatbuffers::FlatBufferBuilder &_fbb, const OneHotOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct AbsOptionsT : public flatbuffers::NativeTable
+{
+ typedef AbsOptions TableType;
+};
+
+struct AbsOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef AbsOptionsT NativeTableType;
+ typedef AbsOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ AbsOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(AbsOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<AbsOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const AbsOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct AbsOptionsBuilder
+{
+ typedef AbsOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit AbsOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<AbsOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<AbsOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<AbsOptions> CreateAbsOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ AbsOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<AbsOptions>
+CreateAbsOptions(flatbuffers::FlatBufferBuilder &_fbb, const AbsOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct HardSwishOptionsT : public flatbuffers::NativeTable
+{
+ typedef HardSwishOptions TableType;
+};
+
+struct HardSwishOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef HardSwishOptionsT NativeTableType;
+ typedef HardSwishOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ HardSwishOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(HardSwishOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<HardSwishOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const HardSwishOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct HardSwishOptionsBuilder
+{
+ typedef HardSwishOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit HardSwishOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<HardSwishOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<HardSwishOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<HardSwishOptions>
+CreateHardSwishOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ HardSwishOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<HardSwishOptions>
+CreateHardSwishOptions(flatbuffers::FlatBufferBuilder &_fbb, const HardSwishOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct LogicalAndOptionsT : public flatbuffers::NativeTable
+{
+ typedef LogicalAndOptions TableType;
+};
+
+struct LogicalAndOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef LogicalAndOptionsT NativeTableType;
+ typedef LogicalAndOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ LogicalAndOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(LogicalAndOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<LogicalAndOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const LogicalAndOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct LogicalAndOptionsBuilder
+{
+ typedef LogicalAndOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit LogicalAndOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<LogicalAndOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<LogicalAndOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<LogicalAndOptions>
+CreateLogicalAndOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ LogicalAndOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<LogicalAndOptions>
+CreateLogicalAndOptions(flatbuffers::FlatBufferBuilder &_fbb, const LogicalAndOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct LogicalNotOptionsT : public flatbuffers::NativeTable
+{
+ typedef LogicalNotOptions TableType;
+};
+
+struct LogicalNotOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef LogicalNotOptionsT NativeTableType;
+ typedef LogicalNotOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ LogicalNotOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(LogicalNotOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<LogicalNotOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const LogicalNotOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct LogicalNotOptionsBuilder
+{
+ typedef LogicalNotOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit LogicalNotOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<LogicalNotOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<LogicalNotOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<LogicalNotOptions>
+CreateLogicalNotOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ LogicalNotOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<LogicalNotOptions>
+CreateLogicalNotOptions(flatbuffers::FlatBufferBuilder &_fbb, const LogicalNotOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct UnpackOptionsT : public flatbuffers::NativeTable
+{
+ typedef UnpackOptions TableType;
+ int32_t num = 0;
+ int32_t axis = 0;
+};
+
+struct UnpackOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef UnpackOptionsT NativeTableType;
+ typedef UnpackOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_NUM = 4,
+ VT_AXIS = 6
+ };
+ int32_t num() const { return GetField<int32_t>(VT_NUM, 0); }
+ int32_t axis() const { return GetField<int32_t>(VT_AXIS, 0); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_NUM) &&
+ VerifyField<int32_t>(verifier, VT_AXIS) && verifier.EndTable();
+ }
+ UnpackOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(UnpackOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<UnpackOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const UnpackOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct UnpackOptionsBuilder
+{
+ typedef UnpackOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_num(int32_t num) { fbb_.AddElement<int32_t>(UnpackOptions::VT_NUM, num, 0); }
+ void add_axis(int32_t axis) { fbb_.AddElement<int32_t>(UnpackOptions::VT_AXIS, axis, 0); }
+ explicit UnpackOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<UnpackOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<UnpackOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<UnpackOptions> CreateUnpackOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ int32_t num = 0, int32_t axis = 0)
+{
+ UnpackOptionsBuilder builder_(_fbb);
+ builder_.add_axis(axis);
+ builder_.add_num(num);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<UnpackOptions>
+CreateUnpackOptions(flatbuffers::FlatBufferBuilder &_fbb, const UnpackOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct FloorDivOptionsT : public flatbuffers::NativeTable
+{
+ typedef FloorDivOptions TableType;
+};
+
+struct FloorDivOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef FloorDivOptionsT NativeTableType;
+ typedef FloorDivOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ FloorDivOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(FloorDivOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<FloorDivOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const FloorDivOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct FloorDivOptionsBuilder
+{
+ typedef FloorDivOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit FloorDivOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<FloorDivOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<FloorDivOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<FloorDivOptions>
+CreateFloorDivOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ FloorDivOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<FloorDivOptions>
+CreateFloorDivOptions(flatbuffers::FlatBufferBuilder &_fbb, const FloorDivOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct SquareOptionsT : public flatbuffers::NativeTable
+{
+ typedef SquareOptions TableType;
+};
+
+struct SquareOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef SquareOptionsT NativeTableType;
+ typedef SquareOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ SquareOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(SquareOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<SquareOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const SquareOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct SquareOptionsBuilder
+{
+ typedef SquareOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit SquareOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<SquareOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<SquareOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<SquareOptions> CreateSquareOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ SquareOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<SquareOptions>
+CreateSquareOptions(flatbuffers::FlatBufferBuilder &_fbb, const SquareOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct ZerosLikeOptionsT : public flatbuffers::NativeTable
+{
+ typedef ZerosLikeOptions TableType;
+};
+
+struct ZerosLikeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef ZerosLikeOptionsT NativeTableType;
+ typedef ZerosLikeOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ ZerosLikeOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(ZerosLikeOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<ZerosLikeOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const ZerosLikeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct ZerosLikeOptionsBuilder
+{
+ typedef ZerosLikeOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit ZerosLikeOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<ZerosLikeOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<ZerosLikeOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<ZerosLikeOptions>
+CreateZerosLikeOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ ZerosLikeOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<ZerosLikeOptions>
+CreateZerosLikeOptions(flatbuffers::FlatBufferBuilder &_fbb, const ZerosLikeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct FillOptionsT : public flatbuffers::NativeTable
+{
+ typedef FillOptions TableType;
+};
+
+struct FillOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef FillOptionsT NativeTableType;
+ typedef FillOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ FillOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(FillOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<FillOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const FillOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct FillOptionsBuilder
+{
+ typedef FillOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit FillOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<FillOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<FillOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<FillOptions> CreateFillOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ FillOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<FillOptions>
+CreateFillOptions(flatbuffers::FlatBufferBuilder &_fbb, const FillOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct FloorModOptionsT : public flatbuffers::NativeTable
+{
+ typedef FloorModOptions TableType;
+};
+
+struct FloorModOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef FloorModOptionsT NativeTableType;
+ typedef FloorModOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ FloorModOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(FloorModOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<FloorModOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const FloorModOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct FloorModOptionsBuilder
+{
+ typedef FloorModOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit FloorModOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<FloorModOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<FloorModOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<FloorModOptions>
+CreateFloorModOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ FloorModOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<FloorModOptions>
+CreateFloorModOptions(flatbuffers::FlatBufferBuilder &_fbb, const FloorModOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct RangeOptionsT : public flatbuffers::NativeTable
+{
+ typedef RangeOptions TableType;
+};
+
+struct RangeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef RangeOptionsT NativeTableType;
+ typedef RangeOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ RangeOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(RangeOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<RangeOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const RangeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct RangeOptionsBuilder
+{
+ typedef RangeOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit RangeOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<RangeOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<RangeOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<RangeOptions> CreateRangeOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ RangeOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<RangeOptions>
+CreateRangeOptions(flatbuffers::FlatBufferBuilder &_fbb, const RangeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct LeakyReluOptionsT : public flatbuffers::NativeTable
+{
+ typedef LeakyReluOptions TableType;
+ float alpha = 0.0f;
+};
+
+struct LeakyReluOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef LeakyReluOptionsT NativeTableType;
+ typedef LeakyReluOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_ALPHA = 4
+ };
+ float alpha() const { return GetField<float>(VT_ALPHA, 0.0f); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<float>(verifier, VT_ALPHA) &&
+ verifier.EndTable();
+ }
+ LeakyReluOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(LeakyReluOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<LeakyReluOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const LeakyReluOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct LeakyReluOptionsBuilder
+{
+ typedef LeakyReluOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_alpha(float alpha) { fbb_.AddElement<float>(LeakyReluOptions::VT_ALPHA, alpha, 0.0f); }
+ explicit LeakyReluOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<LeakyReluOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<LeakyReluOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<LeakyReluOptions>
+CreateLeakyReluOptions(flatbuffers::FlatBufferBuilder &_fbb, float alpha = 0.0f)
+{
+ LeakyReluOptionsBuilder builder_(_fbb);
+ builder_.add_alpha(alpha);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<LeakyReluOptions>
+CreateLeakyReluOptions(flatbuffers::FlatBufferBuilder &_fbb, const LeakyReluOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct SquaredDifferenceOptionsT : public flatbuffers::NativeTable
+{
+ typedef SquaredDifferenceOptions TableType;
+};
+
+struct SquaredDifferenceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef SquaredDifferenceOptionsT NativeTableType;
+ typedef SquaredDifferenceOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ SquaredDifferenceOptionsT *
+ UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(SquaredDifferenceOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<SquaredDifferenceOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const SquaredDifferenceOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct SquaredDifferenceOptionsBuilder
+{
+ typedef SquaredDifferenceOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit SquaredDifferenceOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<SquaredDifferenceOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<SquaredDifferenceOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<SquaredDifferenceOptions>
+CreateSquaredDifferenceOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ SquaredDifferenceOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<SquaredDifferenceOptions>
+CreateSquaredDifferenceOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ const SquaredDifferenceOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct MirrorPadOptionsT : public flatbuffers::NativeTable
+{
+ typedef MirrorPadOptions TableType;
+ circle::MirrorPadMode mode = circle::MirrorPadMode_REFLECT;
+};
+
+struct MirrorPadOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef MirrorPadOptionsT NativeTableType;
+ typedef MirrorPadOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_MODE = 4
+ };
+ circle::MirrorPadMode mode() const
+ {
+ return static_cast<circle::MirrorPadMode>(GetField<int8_t>(VT_MODE, 0));
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_MODE) &&
+ verifier.EndTable();
+ }
+ MirrorPadOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(MirrorPadOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<MirrorPadOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const MirrorPadOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct MirrorPadOptionsBuilder
+{
+ typedef MirrorPadOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_mode(circle::MirrorPadMode mode)
+ {
+ fbb_.AddElement<int8_t>(MirrorPadOptions::VT_MODE, static_cast<int8_t>(mode), 0);
+ }
+ explicit MirrorPadOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<MirrorPadOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<MirrorPadOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<MirrorPadOptions>
+CreateMirrorPadOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ circle::MirrorPadMode mode = circle::MirrorPadMode_REFLECT)
+{
+ MirrorPadOptionsBuilder builder_(_fbb);
+ builder_.add_mode(mode);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<MirrorPadOptions>
+CreateMirrorPadOptions(flatbuffers::FlatBufferBuilder &_fbb, const MirrorPadOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct UniqueOptionsT : public flatbuffers::NativeTable
+{
+ typedef UniqueOptions TableType;
+ circle::TensorType idx_out_type = circle::TensorType_INT32;
+};
+
+struct UniqueOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef UniqueOptionsT NativeTableType;
+ typedef UniqueOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_IDX_OUT_TYPE = 4
+ };
+ circle::TensorType idx_out_type() const
+ {
+ return static_cast<circle::TensorType>(GetField<int8_t>(VT_IDX_OUT_TYPE, 2));
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_IDX_OUT_TYPE) &&
+ verifier.EndTable();
+ }
+ UniqueOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(UniqueOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<UniqueOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const UniqueOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct UniqueOptionsBuilder
+{
+ typedef UniqueOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_idx_out_type(circle::TensorType idx_out_type)
+ {
+ fbb_.AddElement<int8_t>(UniqueOptions::VT_IDX_OUT_TYPE, static_cast<int8_t>(idx_out_type), 2);
+ }
+ explicit UniqueOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<UniqueOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<UniqueOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<UniqueOptions>
+CreateUniqueOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ circle::TensorType idx_out_type = circle::TensorType_INT32)
+{
+ UniqueOptionsBuilder builder_(_fbb);
+ builder_.add_idx_out_type(idx_out_type);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<UniqueOptions>
+CreateUniqueOptions(flatbuffers::FlatBufferBuilder &_fbb, const UniqueOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct ReverseV2OptionsT : public flatbuffers::NativeTable
+{
+ typedef ReverseV2Options TableType;
+};
+
+struct ReverseV2Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef ReverseV2OptionsT NativeTableType;
+ typedef ReverseV2OptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ ReverseV2OptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(ReverseV2OptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<ReverseV2Options>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const ReverseV2OptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct ReverseV2OptionsBuilder
+{
+ typedef ReverseV2Options Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit ReverseV2OptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<ReverseV2Options> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<ReverseV2Options>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<ReverseV2Options>
+CreateReverseV2Options(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ ReverseV2OptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<ReverseV2Options>
+CreateReverseV2Options(flatbuffers::FlatBufferBuilder &_fbb, const ReverseV2OptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct AddNOptionsT : public flatbuffers::NativeTable
+{
+ typedef AddNOptions TableType;
+};
+
+struct AddNOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef AddNOptionsT NativeTableType;
+ typedef AddNOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ AddNOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(AddNOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<AddNOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const AddNOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct AddNOptionsBuilder
+{
+ typedef AddNOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit AddNOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<AddNOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<AddNOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<AddNOptions> CreateAddNOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ AddNOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<AddNOptions>
+CreateAddNOptions(flatbuffers::FlatBufferBuilder &_fbb, const AddNOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct GatherNdOptionsT : public flatbuffers::NativeTable
+{
+ typedef GatherNdOptions TableType;
+};
+
+struct GatherNdOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef GatherNdOptionsT NativeTableType;
+ typedef GatherNdOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ GatherNdOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(GatherNdOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<GatherNdOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const GatherNdOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct GatherNdOptionsBuilder
+{
+ typedef GatherNdOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit GatherNdOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<GatherNdOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<GatherNdOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<GatherNdOptions>
+CreateGatherNdOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ GatherNdOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<GatherNdOptions>
+CreateGatherNdOptions(flatbuffers::FlatBufferBuilder &_fbb, const GatherNdOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct WhereOptionsT : public flatbuffers::NativeTable
+{
+ typedef WhereOptions TableType;
+};
+
+struct WhereOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef WhereOptionsT NativeTableType;
+ typedef WhereOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ WhereOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(WhereOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<WhereOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const WhereOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct WhereOptionsBuilder
+{
+ typedef WhereOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit WhereOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<WhereOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<WhereOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<WhereOptions> CreateWhereOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ WhereOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<WhereOptions>
+CreateWhereOptions(flatbuffers::FlatBufferBuilder &_fbb, const WhereOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct ReverseSequenceOptionsT : public flatbuffers::NativeTable
+{
+ typedef ReverseSequenceOptions TableType;
+ int32_t seq_dim = 0;
+ int32_t batch_dim = 0;
+};
+
+struct ReverseSequenceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef ReverseSequenceOptionsT NativeTableType;
+ typedef ReverseSequenceOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_SEQ_DIM = 4,
+ VT_BATCH_DIM = 6
+ };
+ int32_t seq_dim() const { return GetField<int32_t>(VT_SEQ_DIM, 0); }
+ int32_t batch_dim() const { return GetField<int32_t>(VT_BATCH_DIM, 0); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_SEQ_DIM) &&
+ VerifyField<int32_t>(verifier, VT_BATCH_DIM) && verifier.EndTable();
+ }
+ ReverseSequenceOptionsT *
+ UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(ReverseSequenceOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<ReverseSequenceOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const ReverseSequenceOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct ReverseSequenceOptionsBuilder
+{
+ typedef ReverseSequenceOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_seq_dim(int32_t seq_dim)
+ {
+ fbb_.AddElement<int32_t>(ReverseSequenceOptions::VT_SEQ_DIM, seq_dim, 0);
+ }
+ void add_batch_dim(int32_t batch_dim)
+ {
+ fbb_.AddElement<int32_t>(ReverseSequenceOptions::VT_BATCH_DIM, batch_dim, 0);
+ }
+ explicit ReverseSequenceOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<ReverseSequenceOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<ReverseSequenceOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<ReverseSequenceOptions>
+CreateReverseSequenceOptions(flatbuffers::FlatBufferBuilder &_fbb, int32_t seq_dim = 0,
+ int32_t batch_dim = 0)
+{
+ ReverseSequenceOptionsBuilder builder_(_fbb);
+ builder_.add_batch_dim(batch_dim);
+ builder_.add_seq_dim(seq_dim);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<ReverseSequenceOptions>
+CreateReverseSequenceOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ const ReverseSequenceOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct MatrixDiagOptionsT : public flatbuffers::NativeTable
+{
+ typedef MatrixDiagOptions TableType;
+};
+
+struct MatrixDiagOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef MatrixDiagOptionsT NativeTableType;
+ typedef MatrixDiagOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ MatrixDiagOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(MatrixDiagOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<MatrixDiagOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const MatrixDiagOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct MatrixDiagOptionsBuilder
+{
+ typedef MatrixDiagOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit MatrixDiagOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<MatrixDiagOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<MatrixDiagOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<MatrixDiagOptions>
+CreateMatrixDiagOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ MatrixDiagOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<MatrixDiagOptions>
+CreateMatrixDiagOptions(flatbuffers::FlatBufferBuilder &_fbb, const MatrixDiagOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct QuantizeOptionsT : public flatbuffers::NativeTable
+{
+ typedef QuantizeOptions TableType;
+};
+
+struct QuantizeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef QuantizeOptionsT NativeTableType;
+ typedef QuantizeOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ QuantizeOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(QuantizeOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<QuantizeOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const QuantizeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct QuantizeOptionsBuilder
+{
+ typedef QuantizeOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit QuantizeOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<QuantizeOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<QuantizeOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<QuantizeOptions>
+CreateQuantizeOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ QuantizeOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<QuantizeOptions>
+CreateQuantizeOptions(flatbuffers::FlatBufferBuilder &_fbb, const QuantizeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct MatrixSetDiagOptionsT : public flatbuffers::NativeTable
+{
+ typedef MatrixSetDiagOptions TableType;
+};
+
+struct MatrixSetDiagOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef MatrixSetDiagOptionsT NativeTableType;
+ typedef MatrixSetDiagOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ MatrixSetDiagOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(MatrixSetDiagOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<MatrixSetDiagOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const MatrixSetDiagOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct MatrixSetDiagOptionsBuilder
+{
+ typedef MatrixSetDiagOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit MatrixSetDiagOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<MatrixSetDiagOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<MatrixSetDiagOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<MatrixSetDiagOptions>
+CreateMatrixSetDiagOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ MatrixSetDiagOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<MatrixSetDiagOptions>
+CreateMatrixSetDiagOptions(flatbuffers::FlatBufferBuilder &_fbb, const MatrixSetDiagOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct IfOptionsT : public flatbuffers::NativeTable
+{
+ typedef IfOptions TableType;
+ int32_t then_subgraph_index = 0;
+ int32_t else_subgraph_index = 0;
+};
+
+struct IfOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef IfOptionsT NativeTableType;
+ typedef IfOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_THEN_SUBGRAPH_INDEX = 4,
+ VT_ELSE_SUBGRAPH_INDEX = 6
+ };
+ int32_t then_subgraph_index() const { return GetField<int32_t>(VT_THEN_SUBGRAPH_INDEX, 0); }
+ int32_t else_subgraph_index() const { return GetField<int32_t>(VT_ELSE_SUBGRAPH_INDEX, 0); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_THEN_SUBGRAPH_INDEX) &&
+ VerifyField<int32_t>(verifier, VT_ELSE_SUBGRAPH_INDEX) && verifier.EndTable();
+ }
+ IfOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(IfOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<IfOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const IfOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct IfOptionsBuilder
+{
+ typedef IfOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_then_subgraph_index(int32_t then_subgraph_index)
+ {
+ fbb_.AddElement<int32_t>(IfOptions::VT_THEN_SUBGRAPH_INDEX, then_subgraph_index, 0);
+ }
+ void add_else_subgraph_index(int32_t else_subgraph_index)
+ {
+ fbb_.AddElement<int32_t>(IfOptions::VT_ELSE_SUBGRAPH_INDEX, else_subgraph_index, 0);
+ }
+ explicit IfOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<IfOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<IfOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<IfOptions> CreateIfOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ int32_t then_subgraph_index = 0,
+ int32_t else_subgraph_index = 0)
+{
+ IfOptionsBuilder builder_(_fbb);
+ builder_.add_else_subgraph_index(else_subgraph_index);
+ builder_.add_then_subgraph_index(then_subgraph_index);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<IfOptions>
+CreateIfOptions(flatbuffers::FlatBufferBuilder &_fbb, const IfOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct CallOnceOptionsT : public flatbuffers::NativeTable
+{
+ typedef CallOnceOptions TableType;
+ int32_t init_subgraph_index = 0;
+};
+
+struct CallOnceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef CallOnceOptionsT NativeTableType;
+ typedef CallOnceOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_INIT_SUBGRAPH_INDEX = 4
+ };
+ int32_t init_subgraph_index() const { return GetField<int32_t>(VT_INIT_SUBGRAPH_INDEX, 0); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_INIT_SUBGRAPH_INDEX) &&
+ verifier.EndTable();
+ }
+ CallOnceOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(CallOnceOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<CallOnceOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const CallOnceOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct CallOnceOptionsBuilder
+{
+ typedef CallOnceOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_init_subgraph_index(int32_t init_subgraph_index)
+ {
+ fbb_.AddElement<int32_t>(CallOnceOptions::VT_INIT_SUBGRAPH_INDEX, init_subgraph_index, 0);
+ }
+ explicit CallOnceOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<CallOnceOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<CallOnceOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<CallOnceOptions>
+CreateCallOnceOptions(flatbuffers::FlatBufferBuilder &_fbb, int32_t init_subgraph_index = 0)
+{
+ CallOnceOptionsBuilder builder_(_fbb);
+ builder_.add_init_subgraph_index(init_subgraph_index);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<CallOnceOptions>
+CreateCallOnceOptions(flatbuffers::FlatBufferBuilder &_fbb, const CallOnceOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct WhileOptionsT : public flatbuffers::NativeTable
+{
+ typedef WhileOptions TableType;
+ int32_t cond_subgraph_index = 0;
+ int32_t body_subgraph_index = 0;
+};
+
+struct WhileOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef WhileOptionsT NativeTableType;
+ typedef WhileOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_COND_SUBGRAPH_INDEX = 4,
+ VT_BODY_SUBGRAPH_INDEX = 6
+ };
+ int32_t cond_subgraph_index() const { return GetField<int32_t>(VT_COND_SUBGRAPH_INDEX, 0); }
+ int32_t body_subgraph_index() const { return GetField<int32_t>(VT_BODY_SUBGRAPH_INDEX, 0); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_COND_SUBGRAPH_INDEX) &&
+ VerifyField<int32_t>(verifier, VT_BODY_SUBGRAPH_INDEX) && verifier.EndTable();
+ }
+ WhileOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(WhileOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<WhileOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const WhileOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct WhileOptionsBuilder
+{
+ typedef WhileOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_cond_subgraph_index(int32_t cond_subgraph_index)
+ {
+ fbb_.AddElement<int32_t>(WhileOptions::VT_COND_SUBGRAPH_INDEX, cond_subgraph_index, 0);
+ }
+ void add_body_subgraph_index(int32_t body_subgraph_index)
+ {
+ fbb_.AddElement<int32_t>(WhileOptions::VT_BODY_SUBGRAPH_INDEX, body_subgraph_index, 0);
+ }
+ explicit WhileOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<WhileOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<WhileOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<WhileOptions> CreateWhileOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ int32_t cond_subgraph_index = 0,
+ int32_t body_subgraph_index = 0)
+{
+ WhileOptionsBuilder builder_(_fbb);
+ builder_.add_body_subgraph_index(body_subgraph_index);
+ builder_.add_cond_subgraph_index(cond_subgraph_index);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<WhileOptions>
+CreateWhileOptions(flatbuffers::FlatBufferBuilder &_fbb, const WhileOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct NonMaxSuppressionV4OptionsT : public flatbuffers::NativeTable
+{
+ typedef NonMaxSuppressionV4Options TableType;
+};
+
+struct NonMaxSuppressionV4Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef NonMaxSuppressionV4OptionsT NativeTableType;
+ typedef NonMaxSuppressionV4OptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ NonMaxSuppressionV4OptionsT *
+ UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(NonMaxSuppressionV4OptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<NonMaxSuppressionV4Options>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const NonMaxSuppressionV4OptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct NonMaxSuppressionV4OptionsBuilder
+{
+ typedef NonMaxSuppressionV4Options Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit NonMaxSuppressionV4OptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<NonMaxSuppressionV4Options> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<NonMaxSuppressionV4Options>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<NonMaxSuppressionV4Options>
+CreateNonMaxSuppressionV4Options(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ NonMaxSuppressionV4OptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<NonMaxSuppressionV4Options>
+CreateNonMaxSuppressionV4Options(flatbuffers::FlatBufferBuilder &_fbb,
+ const NonMaxSuppressionV4OptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct NonMaxSuppressionV5OptionsT : public flatbuffers::NativeTable
+{
+ typedef NonMaxSuppressionV5Options TableType;
+};
+
+struct NonMaxSuppressionV5Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef NonMaxSuppressionV5OptionsT NativeTableType;
+ typedef NonMaxSuppressionV5OptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ NonMaxSuppressionV5OptionsT *
+ UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(NonMaxSuppressionV5OptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<NonMaxSuppressionV5Options>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const NonMaxSuppressionV5OptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct NonMaxSuppressionV5OptionsBuilder
+{
+ typedef NonMaxSuppressionV5Options Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit NonMaxSuppressionV5OptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<NonMaxSuppressionV5Options> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<NonMaxSuppressionV5Options>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<NonMaxSuppressionV5Options>
+CreateNonMaxSuppressionV5Options(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ NonMaxSuppressionV5OptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<NonMaxSuppressionV5Options>
+CreateNonMaxSuppressionV5Options(flatbuffers::FlatBufferBuilder &_fbb,
+ const NonMaxSuppressionV5OptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct ScatterNdOptionsT : public flatbuffers::NativeTable
+{
+ typedef ScatterNdOptions TableType;
+};
+
+struct ScatterNdOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef ScatterNdOptionsT NativeTableType;
+ typedef ScatterNdOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ ScatterNdOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(ScatterNdOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<ScatterNdOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const ScatterNdOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct ScatterNdOptionsBuilder
+{
+ typedef ScatterNdOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit ScatterNdOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<ScatterNdOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<ScatterNdOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<ScatterNdOptions>
+CreateScatterNdOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ ScatterNdOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<ScatterNdOptions>
+CreateScatterNdOptions(flatbuffers::FlatBufferBuilder &_fbb, const ScatterNdOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct SelectV2OptionsT : public flatbuffers::NativeTable
+{
+ typedef SelectV2Options TableType;
+};
+
+struct SelectV2Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef SelectV2OptionsT NativeTableType;
+ typedef SelectV2OptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ SelectV2OptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(SelectV2OptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<SelectV2Options>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const SelectV2OptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct SelectV2OptionsBuilder
+{
+ typedef SelectV2Options Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit SelectV2OptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<SelectV2Options> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<SelectV2Options>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<SelectV2Options>
+CreateSelectV2Options(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ SelectV2OptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<SelectV2Options>
+CreateSelectV2Options(flatbuffers::FlatBufferBuilder &_fbb, const SelectV2OptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct DensifyOptionsT : public flatbuffers::NativeTable
+{
+ typedef DensifyOptions TableType;
+};
+
+struct DensifyOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef DensifyOptionsT NativeTableType;
+ typedef DensifyOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ DensifyOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(DensifyOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<DensifyOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const DensifyOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct DensifyOptionsBuilder
+{
+ typedef DensifyOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit DensifyOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<DensifyOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<DensifyOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<DensifyOptions>
+CreateDensifyOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ DensifyOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<DensifyOptions>
+CreateDensifyOptions(flatbuffers::FlatBufferBuilder &_fbb, const DensifyOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct SegmentSumOptionsT : public flatbuffers::NativeTable
+{
+ typedef SegmentSumOptions TableType;
+};
+
+struct SegmentSumOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef SegmentSumOptionsT NativeTableType;
+ typedef SegmentSumOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ SegmentSumOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(SegmentSumOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<SegmentSumOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const SegmentSumOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct SegmentSumOptionsBuilder
+{
+ typedef SegmentSumOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit SegmentSumOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<SegmentSumOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<SegmentSumOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<SegmentSumOptions>
+CreateSegmentSumOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ SegmentSumOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<SegmentSumOptions>
+CreateSegmentSumOptions(flatbuffers::FlatBufferBuilder &_fbb, const SegmentSumOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct BatchMatMulOptionsT : public flatbuffers::NativeTable
+{
+ typedef BatchMatMulOptions TableType;
+ bool adjoint_lhs = false;
+ bool adjoint_rhs = false;
+ bool asymmetric_quantize_inputs = false;
+};
+
+struct BatchMatMulOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef BatchMatMulOptionsT NativeTableType;
+ typedef BatchMatMulOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_ADJOINT_LHS = 4,
+ VT_ADJOINT_RHS = 6,
+ VT_ASYMMETRIC_QUANTIZE_INPUTS = 8
+ };
+ bool adjoint_lhs() const { return GetField<uint8_t>(VT_ADJOINT_LHS, 0) != 0; }
+ bool adjoint_rhs() const { return GetField<uint8_t>(VT_ADJOINT_RHS, 0) != 0; }
+ bool asymmetric_quantize_inputs() const
+ {
+ return GetField<uint8_t>(VT_ASYMMETRIC_QUANTIZE_INPUTS, 0) != 0;
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<uint8_t>(verifier, VT_ADJOINT_LHS) &&
+ VerifyField<uint8_t>(verifier, VT_ADJOINT_RHS) &&
+ VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS) && verifier.EndTable();
+ }
+ BatchMatMulOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(BatchMatMulOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<BatchMatMulOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const BatchMatMulOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct BatchMatMulOptionsBuilder
+{
+ typedef BatchMatMulOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_adjoint_lhs(bool adjoint_lhs)
+ {
+ fbb_.AddElement<uint8_t>(BatchMatMulOptions::VT_ADJOINT_LHS, static_cast<uint8_t>(adjoint_lhs),
+ 0);
+ }
+ void add_adjoint_rhs(bool adjoint_rhs)
+ {
+ fbb_.AddElement<uint8_t>(BatchMatMulOptions::VT_ADJOINT_RHS, static_cast<uint8_t>(adjoint_rhs),
+ 0);
+ }
+ void add_asymmetric_quantize_inputs(bool asymmetric_quantize_inputs)
+ {
+ fbb_.AddElement<uint8_t>(BatchMatMulOptions::VT_ASYMMETRIC_QUANTIZE_INPUTS,
+ static_cast<uint8_t>(asymmetric_quantize_inputs), 0);
+ }
+ explicit BatchMatMulOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<BatchMatMulOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<BatchMatMulOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<BatchMatMulOptions>
+CreateBatchMatMulOptions(flatbuffers::FlatBufferBuilder &_fbb, bool adjoint_lhs = false,
+ bool adjoint_rhs = false, bool asymmetric_quantize_inputs = false)
+{
+ BatchMatMulOptionsBuilder builder_(_fbb);
+ builder_.add_asymmetric_quantize_inputs(asymmetric_quantize_inputs);
+ builder_.add_adjoint_rhs(adjoint_rhs);
+ builder_.add_adjoint_lhs(adjoint_lhs);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<BatchMatMulOptions>
+CreateBatchMatMulOptions(flatbuffers::FlatBufferBuilder &_fbb, const BatchMatMulOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct CumsumOptionsT : public flatbuffers::NativeTable
+{
+ typedef CumsumOptions TableType;
+ bool exclusive = false;
+ bool reverse = false;
+};
+
+struct CumsumOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef CumsumOptionsT NativeTableType;
+ typedef CumsumOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_EXCLUSIVE = 4,
+ VT_REVERSE = 6
+ };
+ bool exclusive() const { return GetField<uint8_t>(VT_EXCLUSIVE, 0) != 0; }
+ bool reverse() const { return GetField<uint8_t>(VT_REVERSE, 0) != 0; }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<uint8_t>(verifier, VT_EXCLUSIVE) &&
+ VerifyField<uint8_t>(verifier, VT_REVERSE) && verifier.EndTable();
+ }
+ CumsumOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(CumsumOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<CumsumOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const CumsumOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct CumsumOptionsBuilder
+{
+ typedef CumsumOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_exclusive(bool exclusive)
+ {
+ fbb_.AddElement<uint8_t>(CumsumOptions::VT_EXCLUSIVE, static_cast<uint8_t>(exclusive), 0);
+ }
+ void add_reverse(bool reverse)
+ {
+ fbb_.AddElement<uint8_t>(CumsumOptions::VT_REVERSE, static_cast<uint8_t>(reverse), 0);
+ }
+ explicit CumsumOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<CumsumOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<CumsumOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<CumsumOptions> CreateCumsumOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ bool exclusive = false,
+ bool reverse = false)
+{
+ CumsumOptionsBuilder builder_(_fbb);
+ builder_.add_reverse(reverse);
+ builder_.add_exclusive(exclusive);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<CumsumOptions>
+CreateCumsumOptions(flatbuffers::FlatBufferBuilder &_fbb, const CumsumOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct BroadcastToOptionsT : public flatbuffers::NativeTable
+{
+ typedef BroadcastToOptions TableType;
+};
+
+struct BroadcastToOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef BroadcastToOptionsT NativeTableType;
+ typedef BroadcastToOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ BroadcastToOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(BroadcastToOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<BroadcastToOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const BroadcastToOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct BroadcastToOptionsBuilder
+{
+ typedef BroadcastToOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit BroadcastToOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<BroadcastToOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<BroadcastToOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<BroadcastToOptions>
+CreateBroadcastToOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ BroadcastToOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<BroadcastToOptions>
+CreateBroadcastToOptions(flatbuffers::FlatBufferBuilder &_fbb, const BroadcastToOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct Rfft2dOptionsT : public flatbuffers::NativeTable
+{
+ typedef Rfft2dOptions TableType;
+};
+
+struct Rfft2dOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef Rfft2dOptionsT NativeTableType;
+ typedef Rfft2dOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ Rfft2dOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(Rfft2dOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<Rfft2dOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const Rfft2dOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct Rfft2dOptionsBuilder
+{
+ typedef Rfft2dOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit Rfft2dOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<Rfft2dOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Rfft2dOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Rfft2dOptions> CreateRfft2dOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ Rfft2dOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<Rfft2dOptions>
+CreateRfft2dOptions(flatbuffers::FlatBufferBuilder &_fbb, const Rfft2dOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct HashtableOptionsT : public flatbuffers::NativeTable
+{
+ typedef HashtableOptions TableType;
+ int32_t table_id = 0;
+ circle::TensorType key_dtype = circle::TensorType_FLOAT32;
+ circle::TensorType value_dtype = circle::TensorType_FLOAT32;
+};
+
+struct HashtableOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef HashtableOptionsT NativeTableType;
+ typedef HashtableOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_TABLE_ID = 4,
+ VT_KEY_DTYPE = 6,
+ VT_VALUE_DTYPE = 8
+ };
+ int32_t table_id() const { return GetField<int32_t>(VT_TABLE_ID, 0); }
+ circle::TensorType key_dtype() const
+ {
+ return static_cast<circle::TensorType>(GetField<int8_t>(VT_KEY_DTYPE, 0));
+ }
+ circle::TensorType value_dtype() const
+ {
+ return static_cast<circle::TensorType>(GetField<int8_t>(VT_VALUE_DTYPE, 0));
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_TABLE_ID) &&
+ VerifyField<int8_t>(verifier, VT_KEY_DTYPE) &&
+ VerifyField<int8_t>(verifier, VT_VALUE_DTYPE) && verifier.EndTable();
+ }
+ HashtableOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(HashtableOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<HashtableOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const HashtableOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct HashtableOptionsBuilder
+{
+ typedef HashtableOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_table_id(int32_t table_id)
+ {
+ fbb_.AddElement<int32_t>(HashtableOptions::VT_TABLE_ID, table_id, 0);
+ }
+ void add_key_dtype(circle::TensorType key_dtype)
+ {
+ fbb_.AddElement<int8_t>(HashtableOptions::VT_KEY_DTYPE, static_cast<int8_t>(key_dtype), 0);
+ }
+ void add_value_dtype(circle::TensorType value_dtype)
+ {
+ fbb_.AddElement<int8_t>(HashtableOptions::VT_VALUE_DTYPE, static_cast<int8_t>(value_dtype), 0);
+ }
+ explicit HashtableOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<HashtableOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<HashtableOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<HashtableOptions>
+CreateHashtableOptions(flatbuffers::FlatBufferBuilder &_fbb, int32_t table_id = 0,
+ circle::TensorType key_dtype = circle::TensorType_FLOAT32,
+ circle::TensorType value_dtype = circle::TensorType_FLOAT32)
+{
+ HashtableOptionsBuilder builder_(_fbb);
+ builder_.add_table_id(table_id);
+ builder_.add_value_dtype(value_dtype);
+ builder_.add_key_dtype(key_dtype);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<HashtableOptions>
+CreateHashtableOptions(flatbuffers::FlatBufferBuilder &_fbb, const HashtableOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct HashtableFindOptionsT : public flatbuffers::NativeTable
+{
+ typedef HashtableFindOptions TableType;
+};
+
+struct HashtableFindOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef HashtableFindOptionsT NativeTableType;
+ typedef HashtableFindOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ HashtableFindOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(HashtableFindOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<HashtableFindOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const HashtableFindOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct HashtableFindOptionsBuilder
+{
+ typedef HashtableFindOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit HashtableFindOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<HashtableFindOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<HashtableFindOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<HashtableFindOptions>
+CreateHashtableFindOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ HashtableFindOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<HashtableFindOptions>
+CreateHashtableFindOptions(flatbuffers::FlatBufferBuilder &_fbb, const HashtableFindOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct HashtableImportOptionsT : public flatbuffers::NativeTable
+{
+ typedef HashtableImportOptions TableType;
+};
+
+struct HashtableImportOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef HashtableImportOptionsT NativeTableType;
+ typedef HashtableImportOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ HashtableImportOptionsT *
+ UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(HashtableImportOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<HashtableImportOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const HashtableImportOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct HashtableImportOptionsBuilder
+{
+ typedef HashtableImportOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit HashtableImportOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<HashtableImportOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<HashtableImportOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<HashtableImportOptions>
+CreateHashtableImportOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ HashtableImportOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<HashtableImportOptions>
+CreateHashtableImportOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ const HashtableImportOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct HashtableSizeOptionsT : public flatbuffers::NativeTable
+{
+ typedef HashtableSizeOptions TableType;
+};
+
+struct HashtableSizeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef HashtableSizeOptionsT NativeTableType;
+ typedef HashtableSizeOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ HashtableSizeOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(HashtableSizeOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<HashtableSizeOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const HashtableSizeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct HashtableSizeOptionsBuilder
+{
+ typedef HashtableSizeOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit HashtableSizeOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<HashtableSizeOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<HashtableSizeOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<HashtableSizeOptions>
+CreateHashtableSizeOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ HashtableSizeOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<HashtableSizeOptions>
+CreateHashtableSizeOptions(flatbuffers::FlatBufferBuilder &_fbb, const HashtableSizeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct VarHandleOptionsT : public flatbuffers::NativeTable
+{
+ typedef VarHandleOptions TableType;
+ std::string container{};
+ std::string shared_name{};
+};
+
+struct VarHandleOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef VarHandleOptionsT NativeTableType;
+ typedef VarHandleOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_CONTAINER = 4,
+ VT_SHARED_NAME = 6
+ };
+ const flatbuffers::String *container() const
+ {
+ return GetPointer<const flatbuffers::String *>(VT_CONTAINER);
+ }
+ const flatbuffers::String *shared_name() const
+ {
+ return GetPointer<const flatbuffers::String *>(VT_SHARED_NAME);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_CONTAINER) &&
+ verifier.VerifyString(container()) && VerifyOffset(verifier, VT_SHARED_NAME) &&
+ verifier.VerifyString(shared_name()) && verifier.EndTable();
+ }
+ VarHandleOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(VarHandleOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<VarHandleOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const VarHandleOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct VarHandleOptionsBuilder
+{
+ typedef VarHandleOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_container(flatbuffers::Offset<flatbuffers::String> container)
+ {
+ fbb_.AddOffset(VarHandleOptions::VT_CONTAINER, container);
+ }
+ void add_shared_name(flatbuffers::Offset<flatbuffers::String> shared_name)
+ {
+ fbb_.AddOffset(VarHandleOptions::VT_SHARED_NAME, shared_name);
+ }
+ explicit VarHandleOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<VarHandleOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<VarHandleOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<VarHandleOptions>
+CreateVarHandleOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::String> container = 0,
+ flatbuffers::Offset<flatbuffers::String> shared_name = 0)
+{
+ VarHandleOptionsBuilder builder_(_fbb);
+ builder_.add_shared_name(shared_name);
+ builder_.add_container(container);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<VarHandleOptions>
+CreateVarHandleOptionsDirect(flatbuffers::FlatBufferBuilder &_fbb, const char *container = nullptr,
+ const char *shared_name = nullptr)
+{
+ auto container__ = container ? _fbb.CreateString(container) : 0;
+ auto shared_name__ = shared_name ? _fbb.CreateString(shared_name) : 0;
+ return circle::CreateVarHandleOptions(_fbb, container__, shared_name__);
+}
+
+flatbuffers::Offset<VarHandleOptions>
+CreateVarHandleOptions(flatbuffers::FlatBufferBuilder &_fbb, const VarHandleOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct ReadVariableOptionsT : public flatbuffers::NativeTable
+{
+ typedef ReadVariableOptions TableType;
+};
+
+struct ReadVariableOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef ReadVariableOptionsT NativeTableType;
+ typedef ReadVariableOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ ReadVariableOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(ReadVariableOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<ReadVariableOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const ReadVariableOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct ReadVariableOptionsBuilder
+{
+ typedef ReadVariableOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit ReadVariableOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<ReadVariableOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<ReadVariableOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<ReadVariableOptions>
+CreateReadVariableOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ ReadVariableOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<ReadVariableOptions>
+CreateReadVariableOptions(flatbuffers::FlatBufferBuilder &_fbb, const ReadVariableOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct AssignVariableOptionsT : public flatbuffers::NativeTable
+{
+ typedef AssignVariableOptions TableType;
+};
+
+struct AssignVariableOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef AssignVariableOptionsT NativeTableType;
+ typedef AssignVariableOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+ AssignVariableOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(AssignVariableOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<AssignVariableOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const AssignVariableOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct AssignVariableOptionsBuilder
+{
+ typedef AssignVariableOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit AssignVariableOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<AssignVariableOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<AssignVariableOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<AssignVariableOptions>
+CreateAssignVariableOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ AssignVariableOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<AssignVariableOptions>
+CreateAssignVariableOptions(flatbuffers::FlatBufferBuilder &_fbb, const AssignVariableOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct RandomOptionsT : public flatbuffers::NativeTable
+{
+ typedef RandomOptions TableType;
+ int32_t seed = 0;
+ int32_t seed2 = 0;
+};
+
+struct RandomOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef RandomOptionsT NativeTableType;
+ typedef RandomOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_SEED = 4,
+ VT_SEED2 = 6
+ };
+ int32_t seed() const { return GetField<int32_t>(VT_SEED, 0); }
+ int32_t seed2() const { return GetField<int32_t>(VT_SEED2, 0); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_SEED) &&
+ VerifyField<int32_t>(verifier, VT_SEED2) && verifier.EndTable();
+ }
+ RandomOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(RandomOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<RandomOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const RandomOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct RandomOptionsBuilder
+{
+ typedef RandomOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_seed(int32_t seed) { fbb_.AddElement<int32_t>(RandomOptions::VT_SEED, seed, 0); }
+ void add_seed2(int32_t seed2) { fbb_.AddElement<int32_t>(RandomOptions::VT_SEED2, seed2, 0); }
+ explicit RandomOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<RandomOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<RandomOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<RandomOptions> CreateRandomOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ int32_t seed = 0, int32_t seed2 = 0)
+{
+ RandomOptionsBuilder builder_(_fbb);
+ builder_.add_seed2(seed2);
+ builder_.add_seed(seed);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<RandomOptions>
+CreateRandomOptions(flatbuffers::FlatBufferBuilder &_fbb, const RandomOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct BCQGatherOptionsT : public flatbuffers::NativeTable
+{
+ typedef BCQGatherOptions TableType;
+ int32_t input_hidden_size = 0;
+ int32_t axis = 0;
+};
+
+struct BCQGatherOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef BCQGatherOptionsT NativeTableType;
+ typedef BCQGatherOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_INPUT_HIDDEN_SIZE = 4,
+ VT_AXIS = 6
+ };
+ int32_t input_hidden_size() const { return GetField<int32_t>(VT_INPUT_HIDDEN_SIZE, 0); }
+ int32_t axis() const { return GetField<int32_t>(VT_AXIS, 0); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_INPUT_HIDDEN_SIZE) &&
+ VerifyField<int32_t>(verifier, VT_AXIS) && verifier.EndTable();
+ }
+ BCQGatherOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(BCQGatherOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<BCQGatherOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const BCQGatherOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct BCQGatherOptionsBuilder
+{
+ typedef BCQGatherOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_input_hidden_size(int32_t input_hidden_size)
+ {
+ fbb_.AddElement<int32_t>(BCQGatherOptions::VT_INPUT_HIDDEN_SIZE, input_hidden_size, 0);
+ }
+ void add_axis(int32_t axis) { fbb_.AddElement<int32_t>(BCQGatherOptions::VT_AXIS, axis, 0); }
+ explicit BCQGatherOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<BCQGatherOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<BCQGatherOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<BCQGatherOptions>
+CreateBCQGatherOptions(flatbuffers::FlatBufferBuilder &_fbb, int32_t input_hidden_size = 0,
+ int32_t axis = 0)
+{
+ BCQGatherOptionsBuilder builder_(_fbb);
+ builder_.add_axis(axis);
+ builder_.add_input_hidden_size(input_hidden_size);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<BCQGatherOptions>
+CreateBCQGatherOptions(flatbuffers::FlatBufferBuilder &_fbb, const BCQGatherOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct BCQFullyConnectedOptionsT : public flatbuffers::NativeTable
+{
+ typedef BCQFullyConnectedOptions TableType;
+ int32_t weights_hidden_size = 0;
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
+};
+
+struct BCQFullyConnectedOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef BCQFullyConnectedOptionsT NativeTableType;
+ typedef BCQFullyConnectedOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_WEIGHTS_HIDDEN_SIZE = 4,
+ VT_FUSED_ACTIVATION_FUNCTION = 6
+ };
+ int32_t weights_hidden_size() const { return GetField<int32_t>(VT_WEIGHTS_HIDDEN_SIZE, 0); }
+ circle::ActivationFunctionType fused_activation_function() const
+ {
+ return static_cast<circle::ActivationFunctionType>(
+ GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_WEIGHTS_HIDDEN_SIZE) &&
+ VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION) && verifier.EndTable();
+ }
+ BCQFullyConnectedOptionsT *
+ UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(BCQFullyConnectedOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<BCQFullyConnectedOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const BCQFullyConnectedOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct BCQFullyConnectedOptionsBuilder
+{
+ typedef BCQFullyConnectedOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_weights_hidden_size(int32_t weights_hidden_size)
+ {
+ fbb_.AddElement<int32_t>(BCQFullyConnectedOptions::VT_WEIGHTS_HIDDEN_SIZE, weights_hidden_size,
+ 0);
+ }
+ void add_fused_activation_function(circle::ActivationFunctionType fused_activation_function)
+ {
+ fbb_.AddElement<int8_t>(BCQFullyConnectedOptions::VT_FUSED_ACTIVATION_FUNCTION,
+ static_cast<int8_t>(fused_activation_function), 0);
+ }
+ explicit BCQFullyConnectedOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<BCQFullyConnectedOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<BCQFullyConnectedOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<BCQFullyConnectedOptions> CreateBCQFullyConnectedOptions(
+ flatbuffers::FlatBufferBuilder &_fbb, int32_t weights_hidden_size = 0,
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE)
+{
+ BCQFullyConnectedOptionsBuilder builder_(_fbb);
+ builder_.add_weights_hidden_size(weights_hidden_size);
+ builder_.add_fused_activation_function(fused_activation_function);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<BCQFullyConnectedOptions>
+CreateBCQFullyConnectedOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ const BCQFullyConnectedOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct InstanceNormOptionsT : public flatbuffers::NativeTable
+{
+ typedef InstanceNormOptions TableType;
+ float epsilon = 0.0f;
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
+};
+
+struct InstanceNormOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef InstanceNormOptionsT NativeTableType;
+ typedef InstanceNormOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_EPSILON = 4,
+ VT_FUSED_ACTIVATION_FUNCTION = 6
+ };
+ float epsilon() const { return GetField<float>(VT_EPSILON, 0.0f); }
+ circle::ActivationFunctionType fused_activation_function() const
+ {
+ return static_cast<circle::ActivationFunctionType>(
+ GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<float>(verifier, VT_EPSILON) &&
+ VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION) && verifier.EndTable();
+ }
+ InstanceNormOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(InstanceNormOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<InstanceNormOptions>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const InstanceNormOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct InstanceNormOptionsBuilder
+{
+ typedef InstanceNormOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_epsilon(float epsilon)
+ {
+ fbb_.AddElement<float>(InstanceNormOptions::VT_EPSILON, epsilon, 0.0f);
+ }
+ void add_fused_activation_function(circle::ActivationFunctionType fused_activation_function)
+ {
+ fbb_.AddElement<int8_t>(InstanceNormOptions::VT_FUSED_ACTIVATION_FUNCTION,
+ static_cast<int8_t>(fused_activation_function), 0);
+ }
+ explicit InstanceNormOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<InstanceNormOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<InstanceNormOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<InstanceNormOptions> CreateInstanceNormOptions(
+ flatbuffers::FlatBufferBuilder &_fbb, float epsilon = 0.0f,
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE)
+{
+ InstanceNormOptionsBuilder builder_(_fbb);
+ builder_.add_epsilon(epsilon);
+ builder_.add_fused_activation_function(fused_activation_function);
+ return builder_.Finish();
+}
+
+flatbuffers::Offset<InstanceNormOptions>
+CreateInstanceNormOptions(flatbuffers::FlatBufferBuilder &_fbb, const InstanceNormOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct OperatorCodeT : public flatbuffers::NativeTable
+{
+ typedef OperatorCode TableType;
+ int8_t deprecated_builtin_code = 0;
+ std::string custom_code{};
+ int32_t version = 1;
+ circle::BuiltinOperator builtin_code = circle::BuiltinOperator_ADD;
+};
+
+struct OperatorCode FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef OperatorCodeT NativeTableType;
+ typedef OperatorCodeBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_DEPRECATED_BUILTIN_CODE = 4,
+ VT_CUSTOM_CODE = 6,
+ VT_VERSION = 8,
+ VT_BUILTIN_CODE = 10
+ };
+ int8_t deprecated_builtin_code() const { return GetField<int8_t>(VT_DEPRECATED_BUILTIN_CODE, 0); }
+ const flatbuffers::String *custom_code() const
+ {
+ return GetPointer<const flatbuffers::String *>(VT_CUSTOM_CODE);
+ }
+ int32_t version() const { return GetField<int32_t>(VT_VERSION, 1); }
+ circle::BuiltinOperator builtin_code() const
+ {
+ return static_cast<circle::BuiltinOperator>(GetField<int32_t>(VT_BUILTIN_CODE, 0));
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) &&
+ VerifyField<int8_t>(verifier, VT_DEPRECATED_BUILTIN_CODE) &&
+ VerifyOffset(verifier, VT_CUSTOM_CODE) && verifier.VerifyString(custom_code()) &&
+ VerifyField<int32_t>(verifier, VT_VERSION) &&
+ VerifyField<int32_t>(verifier, VT_BUILTIN_CODE) && verifier.EndTable();
+ }
+ OperatorCodeT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(OperatorCodeT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<OperatorCode>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const OperatorCodeT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct OperatorCodeBuilder
+{
+ typedef OperatorCode Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_deprecated_builtin_code(int8_t deprecated_builtin_code)
+ {
+ fbb_.AddElement<int8_t>(OperatorCode::VT_DEPRECATED_BUILTIN_CODE, deprecated_builtin_code, 0);
+ }
+ void add_custom_code(flatbuffers::Offset<flatbuffers::String> custom_code)
+ {
+ fbb_.AddOffset(OperatorCode::VT_CUSTOM_CODE, custom_code);
+ }
+ void add_version(int32_t version)
+ {
+ fbb_.AddElement<int32_t>(OperatorCode::VT_VERSION, version, 1);
+ }
+ void add_builtin_code(circle::BuiltinOperator builtin_code)
+ {
+ fbb_.AddElement<int32_t>(OperatorCode::VT_BUILTIN_CODE, static_cast<int32_t>(builtin_code), 0);
+ }
+ explicit OperatorCodeBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<OperatorCode> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<OperatorCode>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<OperatorCode>
+CreateOperatorCode(flatbuffers::FlatBufferBuilder &_fbb, int8_t deprecated_builtin_code = 0,
+ flatbuffers::Offset<flatbuffers::String> custom_code = 0, int32_t version = 1,
+ circle::BuiltinOperator builtin_code = circle::BuiltinOperator_ADD)
+{
+ OperatorCodeBuilder builder_(_fbb);
+ builder_.add_builtin_code(builtin_code);
+ builder_.add_version(version);
+ builder_.add_custom_code(custom_code);
+ builder_.add_deprecated_builtin_code(deprecated_builtin_code);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<OperatorCode>
+CreateOperatorCodeDirect(flatbuffers::FlatBufferBuilder &_fbb, int8_t deprecated_builtin_code = 0,
+ const char *custom_code = nullptr, int32_t version = 1,
+ circle::BuiltinOperator builtin_code = circle::BuiltinOperator_ADD)
+{
+ auto custom_code__ = custom_code ? _fbb.CreateString(custom_code) : 0;
+ return circle::CreateOperatorCode(_fbb, deprecated_builtin_code, custom_code__, version,
+ builtin_code);
+}
+
+flatbuffers::Offset<OperatorCode>
+CreateOperatorCode(flatbuffers::FlatBufferBuilder &_fbb, const OperatorCodeT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct OperatorT : public flatbuffers::NativeTable
+{
+ typedef Operator TableType;
+ uint32_t opcode_index = 0;
+ std::vector<int32_t> inputs{};
+ std::vector<int32_t> outputs{};
+ circle::BuiltinOptionsUnion builtin_options{};
+ std::vector<uint8_t> custom_options{};
+ circle::CustomOptionsFormat custom_options_format = circle::CustomOptionsFormat_FLEXBUFFERS;
+ std::vector<bool> mutating_variable_inputs{};
+ std::vector<int32_t> intermediates{};
+};
+
+struct Operator FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef OperatorT NativeTableType;
+ typedef OperatorBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_OPCODE_INDEX = 4,
+ VT_INPUTS = 6,
+ VT_OUTPUTS = 8,
+ VT_BUILTIN_OPTIONS_TYPE = 10,
+ VT_BUILTIN_OPTIONS = 12,
+ VT_CUSTOM_OPTIONS = 14,
+ VT_CUSTOM_OPTIONS_FORMAT = 16,
+ VT_MUTATING_VARIABLE_INPUTS = 18,
+ VT_INTERMEDIATES = 20
+ };
+ uint32_t opcode_index() const { return GetField<uint32_t>(VT_OPCODE_INDEX, 0); }
+ const flatbuffers::Vector<int32_t> *inputs() const
+ {
+ return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_INPUTS);
+ }
+ const flatbuffers::Vector<int32_t> *outputs() const
+ {
+ return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_OUTPUTS);
+ }
+ circle::BuiltinOptions builtin_options_type() const
+ {
+ return static_cast<circle::BuiltinOptions>(GetField<uint8_t>(VT_BUILTIN_OPTIONS_TYPE, 0));
+ }
+ const void *builtin_options() const { return GetPointer<const void *>(VT_BUILTIN_OPTIONS); }
+ template <typename T> const T *builtin_options_as() const;
+ const circle::Conv2DOptions *builtin_options_as_Conv2DOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_Conv2DOptions
+ ? static_cast<const circle::Conv2DOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::DepthwiseConv2DOptions *builtin_options_as_DepthwiseConv2DOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_DepthwiseConv2DOptions
+ ? static_cast<const circle::DepthwiseConv2DOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::ConcatEmbeddingsOptions *builtin_options_as_ConcatEmbeddingsOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_ConcatEmbeddingsOptions
+ ? static_cast<const circle::ConcatEmbeddingsOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::LSHProjectionOptions *builtin_options_as_LSHProjectionOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_LSHProjectionOptions
+ ? static_cast<const circle::LSHProjectionOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::Pool2DOptions *builtin_options_as_Pool2DOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_Pool2DOptions
+ ? static_cast<const circle::Pool2DOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::SVDFOptions *builtin_options_as_SVDFOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_SVDFOptions
+ ? static_cast<const circle::SVDFOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::RNNOptions *builtin_options_as_RNNOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_RNNOptions
+ ? static_cast<const circle::RNNOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::FullyConnectedOptions *builtin_options_as_FullyConnectedOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_FullyConnectedOptions
+ ? static_cast<const circle::FullyConnectedOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::SoftmaxOptions *builtin_options_as_SoftmaxOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_SoftmaxOptions
+ ? static_cast<const circle::SoftmaxOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::ConcatenationOptions *builtin_options_as_ConcatenationOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_ConcatenationOptions
+ ? static_cast<const circle::ConcatenationOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::AddOptions *builtin_options_as_AddOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_AddOptions
+ ? static_cast<const circle::AddOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::L2NormOptions *builtin_options_as_L2NormOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_L2NormOptions
+ ? static_cast<const circle::L2NormOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::LocalResponseNormalizationOptions *
+ builtin_options_as_LocalResponseNormalizationOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_LocalResponseNormalizationOptions
+ ? static_cast<const circle::LocalResponseNormalizationOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::LSTMOptions *builtin_options_as_LSTMOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_LSTMOptions
+ ? static_cast<const circle::LSTMOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::ResizeBilinearOptions *builtin_options_as_ResizeBilinearOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_ResizeBilinearOptions
+ ? static_cast<const circle::ResizeBilinearOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::CallOptions *builtin_options_as_CallOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_CallOptions
+ ? static_cast<const circle::CallOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::ReshapeOptions *builtin_options_as_ReshapeOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_ReshapeOptions
+ ? static_cast<const circle::ReshapeOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::SkipGramOptions *builtin_options_as_SkipGramOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_SkipGramOptions
+ ? static_cast<const circle::SkipGramOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::SpaceToDepthOptions *builtin_options_as_SpaceToDepthOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_SpaceToDepthOptions
+ ? static_cast<const circle::SpaceToDepthOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::EmbeddingLookupSparseOptions *
+ builtin_options_as_EmbeddingLookupSparseOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_EmbeddingLookupSparseOptions
+ ? static_cast<const circle::EmbeddingLookupSparseOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::MulOptions *builtin_options_as_MulOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_MulOptions
+ ? static_cast<const circle::MulOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::PadOptions *builtin_options_as_PadOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_PadOptions
+ ? static_cast<const circle::PadOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::GatherOptions *builtin_options_as_GatherOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_GatherOptions
+ ? static_cast<const circle::GatherOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::BatchToSpaceNDOptions *builtin_options_as_BatchToSpaceNDOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_BatchToSpaceNDOptions
+ ? static_cast<const circle::BatchToSpaceNDOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::SpaceToBatchNDOptions *builtin_options_as_SpaceToBatchNDOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_SpaceToBatchNDOptions
+ ? static_cast<const circle::SpaceToBatchNDOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::TransposeOptions *builtin_options_as_TransposeOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_TransposeOptions
+ ? static_cast<const circle::TransposeOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::ReducerOptions *builtin_options_as_ReducerOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_ReducerOptions
+ ? static_cast<const circle::ReducerOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::SubOptions *builtin_options_as_SubOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_SubOptions
+ ? static_cast<const circle::SubOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::DivOptions *builtin_options_as_DivOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_DivOptions
+ ? static_cast<const circle::DivOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::SqueezeOptions *builtin_options_as_SqueezeOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_SqueezeOptions
+ ? static_cast<const circle::SqueezeOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::SequenceRNNOptions *builtin_options_as_SequenceRNNOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_SequenceRNNOptions
+ ? static_cast<const circle::SequenceRNNOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::StridedSliceOptions *builtin_options_as_StridedSliceOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_StridedSliceOptions
+ ? static_cast<const circle::StridedSliceOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::ExpOptions *builtin_options_as_ExpOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_ExpOptions
+ ? static_cast<const circle::ExpOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::TopKV2Options *builtin_options_as_TopKV2Options() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_TopKV2Options
+ ? static_cast<const circle::TopKV2Options *>(builtin_options())
+ : nullptr;
+ }
+ const circle::SplitOptions *builtin_options_as_SplitOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_SplitOptions
+ ? static_cast<const circle::SplitOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::LogSoftmaxOptions *builtin_options_as_LogSoftmaxOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_LogSoftmaxOptions
+ ? static_cast<const circle::LogSoftmaxOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::CastOptions *builtin_options_as_CastOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_CastOptions
+ ? static_cast<const circle::CastOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::DequantizeOptions *builtin_options_as_DequantizeOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_DequantizeOptions
+ ? static_cast<const circle::DequantizeOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::MaximumMinimumOptions *builtin_options_as_MaximumMinimumOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_MaximumMinimumOptions
+ ? static_cast<const circle::MaximumMinimumOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::ArgMaxOptions *builtin_options_as_ArgMaxOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_ArgMaxOptions
+ ? static_cast<const circle::ArgMaxOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::LessOptions *builtin_options_as_LessOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_LessOptions
+ ? static_cast<const circle::LessOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::NegOptions *builtin_options_as_NegOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_NegOptions
+ ? static_cast<const circle::NegOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::PadV2Options *builtin_options_as_PadV2Options() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_PadV2Options
+ ? static_cast<const circle::PadV2Options *>(builtin_options())
+ : nullptr;
+ }
+ const circle::GreaterOptions *builtin_options_as_GreaterOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_GreaterOptions
+ ? static_cast<const circle::GreaterOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::GreaterEqualOptions *builtin_options_as_GreaterEqualOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_GreaterEqualOptions
+ ? static_cast<const circle::GreaterEqualOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::LessEqualOptions *builtin_options_as_LessEqualOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_LessEqualOptions
+ ? static_cast<const circle::LessEqualOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::SelectOptions *builtin_options_as_SelectOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_SelectOptions
+ ? static_cast<const circle::SelectOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::SliceOptions *builtin_options_as_SliceOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_SliceOptions
+ ? static_cast<const circle::SliceOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::TransposeConvOptions *builtin_options_as_TransposeConvOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_TransposeConvOptions
+ ? static_cast<const circle::TransposeConvOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::SparseToDenseOptions *builtin_options_as_SparseToDenseOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_SparseToDenseOptions
+ ? static_cast<const circle::SparseToDenseOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::TileOptions *builtin_options_as_TileOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_TileOptions
+ ? static_cast<const circle::TileOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::ExpandDimsOptions *builtin_options_as_ExpandDimsOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_ExpandDimsOptions
+ ? static_cast<const circle::ExpandDimsOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::EqualOptions *builtin_options_as_EqualOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_EqualOptions
+ ? static_cast<const circle::EqualOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::NotEqualOptions *builtin_options_as_NotEqualOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_NotEqualOptions
+ ? static_cast<const circle::NotEqualOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::ShapeOptions *builtin_options_as_ShapeOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_ShapeOptions
+ ? static_cast<const circle::ShapeOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::PowOptions *builtin_options_as_PowOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_PowOptions
+ ? static_cast<const circle::PowOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::ArgMinOptions *builtin_options_as_ArgMinOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_ArgMinOptions
+ ? static_cast<const circle::ArgMinOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::FakeQuantOptions *builtin_options_as_FakeQuantOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_FakeQuantOptions
+ ? static_cast<const circle::FakeQuantOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::PackOptions *builtin_options_as_PackOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_PackOptions
+ ? static_cast<const circle::PackOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::LogicalOrOptions *builtin_options_as_LogicalOrOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_LogicalOrOptions
+ ? static_cast<const circle::LogicalOrOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::OneHotOptions *builtin_options_as_OneHotOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_OneHotOptions
+ ? static_cast<const circle::OneHotOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::LogicalAndOptions *builtin_options_as_LogicalAndOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_LogicalAndOptions
+ ? static_cast<const circle::LogicalAndOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::LogicalNotOptions *builtin_options_as_LogicalNotOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_LogicalNotOptions
+ ? static_cast<const circle::LogicalNotOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::UnpackOptions *builtin_options_as_UnpackOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_UnpackOptions
+ ? static_cast<const circle::UnpackOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::FloorDivOptions *builtin_options_as_FloorDivOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_FloorDivOptions
+ ? static_cast<const circle::FloorDivOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::SquareOptions *builtin_options_as_SquareOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_SquareOptions
+ ? static_cast<const circle::SquareOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::ZerosLikeOptions *builtin_options_as_ZerosLikeOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_ZerosLikeOptions
+ ? static_cast<const circle::ZerosLikeOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::FillOptions *builtin_options_as_FillOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_FillOptions
+ ? static_cast<const circle::FillOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::BidirectionalSequenceLSTMOptions *
+ builtin_options_as_BidirectionalSequenceLSTMOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_BidirectionalSequenceLSTMOptions
+ ? static_cast<const circle::BidirectionalSequenceLSTMOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::BidirectionalSequenceRNNOptions *
+ builtin_options_as_BidirectionalSequenceRNNOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_BidirectionalSequenceRNNOptions
+ ? static_cast<const circle::BidirectionalSequenceRNNOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::UnidirectionalSequenceLSTMOptions *
+ builtin_options_as_UnidirectionalSequenceLSTMOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_UnidirectionalSequenceLSTMOptions
+ ? static_cast<const circle::UnidirectionalSequenceLSTMOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::FloorModOptions *builtin_options_as_FloorModOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_FloorModOptions
+ ? static_cast<const circle::FloorModOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::RangeOptions *builtin_options_as_RangeOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_RangeOptions
+ ? static_cast<const circle::RangeOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::ResizeNearestNeighborOptions *
+ builtin_options_as_ResizeNearestNeighborOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_ResizeNearestNeighborOptions
+ ? static_cast<const circle::ResizeNearestNeighborOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::LeakyReluOptions *builtin_options_as_LeakyReluOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_LeakyReluOptions
+ ? static_cast<const circle::LeakyReluOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::SquaredDifferenceOptions *builtin_options_as_SquaredDifferenceOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_SquaredDifferenceOptions
+ ? static_cast<const circle::SquaredDifferenceOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::MirrorPadOptions *builtin_options_as_MirrorPadOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_MirrorPadOptions
+ ? static_cast<const circle::MirrorPadOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::AbsOptions *builtin_options_as_AbsOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_AbsOptions
+ ? static_cast<const circle::AbsOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::SplitVOptions *builtin_options_as_SplitVOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_SplitVOptions
+ ? static_cast<const circle::SplitVOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::UniqueOptions *builtin_options_as_UniqueOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_UniqueOptions
+ ? static_cast<const circle::UniqueOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::ReverseV2Options *builtin_options_as_ReverseV2Options() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_ReverseV2Options
+ ? static_cast<const circle::ReverseV2Options *>(builtin_options())
+ : nullptr;
+ }
+ const circle::AddNOptions *builtin_options_as_AddNOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_AddNOptions
+ ? static_cast<const circle::AddNOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::GatherNdOptions *builtin_options_as_GatherNdOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_GatherNdOptions
+ ? static_cast<const circle::GatherNdOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::CosOptions *builtin_options_as_CosOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_CosOptions
+ ? static_cast<const circle::CosOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::WhereOptions *builtin_options_as_WhereOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_WhereOptions
+ ? static_cast<const circle::WhereOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::RankOptions *builtin_options_as_RankOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_RankOptions
+ ? static_cast<const circle::RankOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::ReverseSequenceOptions *builtin_options_as_ReverseSequenceOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_ReverseSequenceOptions
+ ? static_cast<const circle::ReverseSequenceOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::MatrixDiagOptions *builtin_options_as_MatrixDiagOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_MatrixDiagOptions
+ ? static_cast<const circle::MatrixDiagOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::QuantizeOptions *builtin_options_as_QuantizeOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_QuantizeOptions
+ ? static_cast<const circle::QuantizeOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::MatrixSetDiagOptions *builtin_options_as_MatrixSetDiagOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_MatrixSetDiagOptions
+ ? static_cast<const circle::MatrixSetDiagOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::HardSwishOptions *builtin_options_as_HardSwishOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_HardSwishOptions
+ ? static_cast<const circle::HardSwishOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::IfOptions *builtin_options_as_IfOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_IfOptions
+ ? static_cast<const circle::IfOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::WhileOptions *builtin_options_as_WhileOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_WhileOptions
+ ? static_cast<const circle::WhileOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::DepthToSpaceOptions *builtin_options_as_DepthToSpaceOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_DepthToSpaceOptions
+ ? static_cast<const circle::DepthToSpaceOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::NonMaxSuppressionV4Options *builtin_options_as_NonMaxSuppressionV4Options() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_NonMaxSuppressionV4Options
+ ? static_cast<const circle::NonMaxSuppressionV4Options *>(builtin_options())
+ : nullptr;
+ }
+ const circle::NonMaxSuppressionV5Options *builtin_options_as_NonMaxSuppressionV5Options() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_NonMaxSuppressionV5Options
+ ? static_cast<const circle::NonMaxSuppressionV5Options *>(builtin_options())
+ : nullptr;
+ }
+ const circle::ScatterNdOptions *builtin_options_as_ScatterNdOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_ScatterNdOptions
+ ? static_cast<const circle::ScatterNdOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::SelectV2Options *builtin_options_as_SelectV2Options() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_SelectV2Options
+ ? static_cast<const circle::SelectV2Options *>(builtin_options())
+ : nullptr;
+ }
+ const circle::DensifyOptions *builtin_options_as_DensifyOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_DensifyOptions
+ ? static_cast<const circle::DensifyOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::SegmentSumOptions *builtin_options_as_SegmentSumOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_SegmentSumOptions
+ ? static_cast<const circle::SegmentSumOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::BatchMatMulOptions *builtin_options_as_BatchMatMulOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_BatchMatMulOptions
+ ? static_cast<const circle::BatchMatMulOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::CumsumOptions *builtin_options_as_CumsumOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_CumsumOptions
+ ? static_cast<const circle::CumsumOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::CallOnceOptions *builtin_options_as_CallOnceOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_CallOnceOptions
+ ? static_cast<const circle::CallOnceOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::BroadcastToOptions *builtin_options_as_BroadcastToOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_BroadcastToOptions
+ ? static_cast<const circle::BroadcastToOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::Rfft2dOptions *builtin_options_as_Rfft2dOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_Rfft2dOptions
+ ? static_cast<const circle::Rfft2dOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::Conv3DOptions *builtin_options_as_Conv3DOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_Conv3DOptions
+ ? static_cast<const circle::Conv3DOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::HashtableOptions *builtin_options_as_HashtableOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_HashtableOptions
+ ? static_cast<const circle::HashtableOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::HashtableFindOptions *builtin_options_as_HashtableFindOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_HashtableFindOptions
+ ? static_cast<const circle::HashtableFindOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::HashtableImportOptions *builtin_options_as_HashtableImportOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_HashtableImportOptions
+ ? static_cast<const circle::HashtableImportOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::HashtableSizeOptions *builtin_options_as_HashtableSizeOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_HashtableSizeOptions
+ ? static_cast<const circle::HashtableSizeOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::VarHandleOptions *builtin_options_as_VarHandleOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_VarHandleOptions
+ ? static_cast<const circle::VarHandleOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::ReadVariableOptions *builtin_options_as_ReadVariableOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_ReadVariableOptions
+ ? static_cast<const circle::ReadVariableOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::AssignVariableOptions *builtin_options_as_AssignVariableOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_AssignVariableOptions
+ ? static_cast<const circle::AssignVariableOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::RandomOptions *builtin_options_as_RandomOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_RandomOptions
+ ? static_cast<const circle::RandomOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::BCQGatherOptions *builtin_options_as_BCQGatherOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_BCQGatherOptions
+ ? static_cast<const circle::BCQGatherOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::BCQFullyConnectedOptions *builtin_options_as_BCQFullyConnectedOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_BCQFullyConnectedOptions
+ ? static_cast<const circle::BCQFullyConnectedOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::InstanceNormOptions *builtin_options_as_InstanceNormOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_InstanceNormOptions
+ ? static_cast<const circle::InstanceNormOptions *>(builtin_options())
+ : nullptr;
+ }
+ const flatbuffers::Vector<uint8_t> *custom_options() const
+ {
+ return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_CUSTOM_OPTIONS);
+ }
+ circle::CustomOptionsFormat custom_options_format() const
+ {
+ return static_cast<circle::CustomOptionsFormat>(GetField<int8_t>(VT_CUSTOM_OPTIONS_FORMAT, 0));
+ }
+ const flatbuffers::Vector<uint8_t> *mutating_variable_inputs() const
+ {
+ return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_MUTATING_VARIABLE_INPUTS);
+ }
+ const flatbuffers::Vector<int32_t> *intermediates() const
+ {
+ return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_INTERMEDIATES);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<uint32_t>(verifier, VT_OPCODE_INDEX) &&
+ VerifyOffset(verifier, VT_INPUTS) && verifier.VerifyVector(inputs()) &&
+ VerifyOffset(verifier, VT_OUTPUTS) && verifier.VerifyVector(outputs()) &&
+ VerifyField<uint8_t>(verifier, VT_BUILTIN_OPTIONS_TYPE) &&
+ VerifyOffset(verifier, VT_BUILTIN_OPTIONS) &&
+ VerifyBuiltinOptions(verifier, builtin_options(), builtin_options_type()) &&
+ VerifyOffset(verifier, VT_CUSTOM_OPTIONS) && verifier.VerifyVector(custom_options()) &&
+ VerifyField<int8_t>(verifier, VT_CUSTOM_OPTIONS_FORMAT) &&
+ VerifyOffset(verifier, VT_MUTATING_VARIABLE_INPUTS) &&
+ verifier.VerifyVector(mutating_variable_inputs()) &&
+ VerifyOffset(verifier, VT_INTERMEDIATES) && verifier.VerifyVector(intermediates()) &&
+ verifier.EndTable();
+ }
+ OperatorT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(OperatorT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<Operator>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const OperatorT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+template <>
+inline const circle::Conv2DOptions *Operator::builtin_options_as<circle::Conv2DOptions>() const
+{
+ return builtin_options_as_Conv2DOptions();
+}
+
+template <>
+inline const circle::DepthwiseConv2DOptions *
+Operator::builtin_options_as<circle::DepthwiseConv2DOptions>() const
+{
+ return builtin_options_as_DepthwiseConv2DOptions();
+}
+
+template <>
+inline const circle::ConcatEmbeddingsOptions *
+Operator::builtin_options_as<circle::ConcatEmbeddingsOptions>() const
+{
+ return builtin_options_as_ConcatEmbeddingsOptions();
+}
+
+template <>
+inline const circle::LSHProjectionOptions *
+Operator::builtin_options_as<circle::LSHProjectionOptions>() const
+{
+ return builtin_options_as_LSHProjectionOptions();
+}
+
+template <>
+inline const circle::Pool2DOptions *Operator::builtin_options_as<circle::Pool2DOptions>() const
+{
+ return builtin_options_as_Pool2DOptions();
+}
+
+template <>
+inline const circle::SVDFOptions *Operator::builtin_options_as<circle::SVDFOptions>() const
+{
+ return builtin_options_as_SVDFOptions();
+}
+
+template <>
+inline const circle::RNNOptions *Operator::builtin_options_as<circle::RNNOptions>() const
+{
+ return builtin_options_as_RNNOptions();
+}
+
+template <>
+inline const circle::FullyConnectedOptions *
+Operator::builtin_options_as<circle::FullyConnectedOptions>() const
+{
+ return builtin_options_as_FullyConnectedOptions();
+}
+
+template <>
+inline const circle::SoftmaxOptions *Operator::builtin_options_as<circle::SoftmaxOptions>() const
+{
+ return builtin_options_as_SoftmaxOptions();
+}
+
+template <>
+inline const circle::ConcatenationOptions *
+Operator::builtin_options_as<circle::ConcatenationOptions>() const
+{
+ return builtin_options_as_ConcatenationOptions();
+}
+
+template <>
+inline const circle::AddOptions *Operator::builtin_options_as<circle::AddOptions>() const
+{
+ return builtin_options_as_AddOptions();
+}
+
+template <>
+inline const circle::L2NormOptions *Operator::builtin_options_as<circle::L2NormOptions>() const
+{
+ return builtin_options_as_L2NormOptions();
+}
+
+template <>
+inline const circle::LocalResponseNormalizationOptions *
+Operator::builtin_options_as<circle::LocalResponseNormalizationOptions>() const
+{
+ return builtin_options_as_LocalResponseNormalizationOptions();
+}
+
+template <>
+inline const circle::LSTMOptions *Operator::builtin_options_as<circle::LSTMOptions>() const
+{
+ return builtin_options_as_LSTMOptions();
+}
+
+template <>
+inline const circle::ResizeBilinearOptions *
+Operator::builtin_options_as<circle::ResizeBilinearOptions>() const
+{
+ return builtin_options_as_ResizeBilinearOptions();
+}
+
+template <>
+inline const circle::CallOptions *Operator::builtin_options_as<circle::CallOptions>() const
+{
+ return builtin_options_as_CallOptions();
+}
+
+template <>
+inline const circle::ReshapeOptions *Operator::builtin_options_as<circle::ReshapeOptions>() const
+{
+ return builtin_options_as_ReshapeOptions();
+}
+
+template <>
+inline const circle::SkipGramOptions *Operator::builtin_options_as<circle::SkipGramOptions>() const
+{
+ return builtin_options_as_SkipGramOptions();
+}
+
+template <>
+inline const circle::SpaceToDepthOptions *
+Operator::builtin_options_as<circle::SpaceToDepthOptions>() const
+{
+ return builtin_options_as_SpaceToDepthOptions();
+}
+
+template <>
+inline const circle::EmbeddingLookupSparseOptions *
+Operator::builtin_options_as<circle::EmbeddingLookupSparseOptions>() const
+{
+ return builtin_options_as_EmbeddingLookupSparseOptions();
+}
+
+template <>
+inline const circle::MulOptions *Operator::builtin_options_as<circle::MulOptions>() const
+{
+ return builtin_options_as_MulOptions();
+}
+
+template <>
+inline const circle::PadOptions *Operator::builtin_options_as<circle::PadOptions>() const
+{
+ return builtin_options_as_PadOptions();
+}
+
+template <>
+inline const circle::GatherOptions *Operator::builtin_options_as<circle::GatherOptions>() const
+{
+ return builtin_options_as_GatherOptions();
+}
+
+template <>
+inline const circle::BatchToSpaceNDOptions *
+Operator::builtin_options_as<circle::BatchToSpaceNDOptions>() const
+{
+ return builtin_options_as_BatchToSpaceNDOptions();
+}
+
+template <>
+inline const circle::SpaceToBatchNDOptions *
+Operator::builtin_options_as<circle::SpaceToBatchNDOptions>() const
+{
+ return builtin_options_as_SpaceToBatchNDOptions();
+}
+
+template <>
+inline const circle::TransposeOptions *
+Operator::builtin_options_as<circle::TransposeOptions>() const
+{
+ return builtin_options_as_TransposeOptions();
+}
+
+template <>
+inline const circle::ReducerOptions *Operator::builtin_options_as<circle::ReducerOptions>() const
+{
+ return builtin_options_as_ReducerOptions();
+}
+
+template <>
+inline const circle::SubOptions *Operator::builtin_options_as<circle::SubOptions>() const
+{
+ return builtin_options_as_SubOptions();
+}
+
+template <>
+inline const circle::DivOptions *Operator::builtin_options_as<circle::DivOptions>() const
+{
+ return builtin_options_as_DivOptions();
+}
+
+template <>
+inline const circle::SqueezeOptions *Operator::builtin_options_as<circle::SqueezeOptions>() const
+{
+ return builtin_options_as_SqueezeOptions();
+}
+
+template <>
+inline const circle::SequenceRNNOptions *
+Operator::builtin_options_as<circle::SequenceRNNOptions>() const
+{
+ return builtin_options_as_SequenceRNNOptions();
+}
+
+template <>
+inline const circle::StridedSliceOptions *
+Operator::builtin_options_as<circle::StridedSliceOptions>() const
+{
+ return builtin_options_as_StridedSliceOptions();
+}
+
+template <>
+inline const circle::ExpOptions *Operator::builtin_options_as<circle::ExpOptions>() const
+{
+ return builtin_options_as_ExpOptions();
+}
+
+template <>
+inline const circle::TopKV2Options *Operator::builtin_options_as<circle::TopKV2Options>() const
+{
+ return builtin_options_as_TopKV2Options();
+}
+
+template <>
+inline const circle::SplitOptions *Operator::builtin_options_as<circle::SplitOptions>() const
+{
+ return builtin_options_as_SplitOptions();
+}
+
+template <>
+inline const circle::LogSoftmaxOptions *
+Operator::builtin_options_as<circle::LogSoftmaxOptions>() const
+{
+ return builtin_options_as_LogSoftmaxOptions();
+}
+
+template <>
+inline const circle::CastOptions *Operator::builtin_options_as<circle::CastOptions>() const
+{
+ return builtin_options_as_CastOptions();
+}
+
+template <>
+inline const circle::DequantizeOptions *
+Operator::builtin_options_as<circle::DequantizeOptions>() const
+{
+ return builtin_options_as_DequantizeOptions();
+}
+
+template <>
+inline const circle::MaximumMinimumOptions *
+Operator::builtin_options_as<circle::MaximumMinimumOptions>() const
+{
+ return builtin_options_as_MaximumMinimumOptions();
+}
+
+template <>
+inline const circle::ArgMaxOptions *Operator::builtin_options_as<circle::ArgMaxOptions>() const
+{
+ return builtin_options_as_ArgMaxOptions();
+}
+
+template <>
+inline const circle::LessOptions *Operator::builtin_options_as<circle::LessOptions>() const
+{
+ return builtin_options_as_LessOptions();
+}
+
+template <>
+inline const circle::NegOptions *Operator::builtin_options_as<circle::NegOptions>() const
+{
+ return builtin_options_as_NegOptions();
+}
+
+template <>
+inline const circle::PadV2Options *Operator::builtin_options_as<circle::PadV2Options>() const
+{
+ return builtin_options_as_PadV2Options();
+}
+
+template <>
+inline const circle::GreaterOptions *Operator::builtin_options_as<circle::GreaterOptions>() const
+{
+ return builtin_options_as_GreaterOptions();
+}
+
+template <>
+inline const circle::GreaterEqualOptions *
+Operator::builtin_options_as<circle::GreaterEqualOptions>() const
+{
+ return builtin_options_as_GreaterEqualOptions();
+}
+
+template <>
+inline const circle::LessEqualOptions *
+Operator::builtin_options_as<circle::LessEqualOptions>() const
+{
+ return builtin_options_as_LessEqualOptions();
+}
+
+template <>
+inline const circle::SelectOptions *Operator::builtin_options_as<circle::SelectOptions>() const
+{
+ return builtin_options_as_SelectOptions();
+}
+
+template <>
+inline const circle::SliceOptions *Operator::builtin_options_as<circle::SliceOptions>() const
+{
+ return builtin_options_as_SliceOptions();
+}
+
+template <>
+inline const circle::TransposeConvOptions *
+Operator::builtin_options_as<circle::TransposeConvOptions>() const
+{
+ return builtin_options_as_TransposeConvOptions();
+}
+
+template <>
+inline const circle::SparseToDenseOptions *
+Operator::builtin_options_as<circle::SparseToDenseOptions>() const
+{
+ return builtin_options_as_SparseToDenseOptions();
+}
+
+template <>
+inline const circle::TileOptions *Operator::builtin_options_as<circle::TileOptions>() const
+{
+ return builtin_options_as_TileOptions();
+}
+
+template <>
+inline const circle::ExpandDimsOptions *
+Operator::builtin_options_as<circle::ExpandDimsOptions>() const
+{
+ return builtin_options_as_ExpandDimsOptions();
+}
+
+template <>
+inline const circle::EqualOptions *Operator::builtin_options_as<circle::EqualOptions>() const
+{
+ return builtin_options_as_EqualOptions();
+}
+
+template <>
+inline const circle::NotEqualOptions *Operator::builtin_options_as<circle::NotEqualOptions>() const
+{
+ return builtin_options_as_NotEqualOptions();
+}
+
+template <>
+inline const circle::ShapeOptions *Operator::builtin_options_as<circle::ShapeOptions>() const
+{
+ return builtin_options_as_ShapeOptions();
+}
+
+template <>
+inline const circle::PowOptions *Operator::builtin_options_as<circle::PowOptions>() const
+{
+ return builtin_options_as_PowOptions();
+}
+
+template <>
+inline const circle::ArgMinOptions *Operator::builtin_options_as<circle::ArgMinOptions>() const
+{
+ return builtin_options_as_ArgMinOptions();
+}
+
+template <>
+inline const circle::FakeQuantOptions *
+Operator::builtin_options_as<circle::FakeQuantOptions>() const
+{
+ return builtin_options_as_FakeQuantOptions();
+}
+
+template <>
+inline const circle::PackOptions *Operator::builtin_options_as<circle::PackOptions>() const
+{
+ return builtin_options_as_PackOptions();
+}
+
+template <>
+inline const circle::LogicalOrOptions *
+Operator::builtin_options_as<circle::LogicalOrOptions>() const
+{
+ return builtin_options_as_LogicalOrOptions();
+}
+
+template <>
+inline const circle::OneHotOptions *Operator::builtin_options_as<circle::OneHotOptions>() const
+{
+ return builtin_options_as_OneHotOptions();
+}
+
+template <>
+inline const circle::LogicalAndOptions *
+Operator::builtin_options_as<circle::LogicalAndOptions>() const
+{
+ return builtin_options_as_LogicalAndOptions();
+}
+
+template <>
+inline const circle::LogicalNotOptions *
+Operator::builtin_options_as<circle::LogicalNotOptions>() const
+{
+ return builtin_options_as_LogicalNotOptions();
+}
+
+template <>
+inline const circle::UnpackOptions *Operator::builtin_options_as<circle::UnpackOptions>() const
+{
+ return builtin_options_as_UnpackOptions();
+}
+
+template <>
+inline const circle::FloorDivOptions *Operator::builtin_options_as<circle::FloorDivOptions>() const
+{
+ return builtin_options_as_FloorDivOptions();
+}
+
+template <>
+inline const circle::SquareOptions *Operator::builtin_options_as<circle::SquareOptions>() const
+{
+ return builtin_options_as_SquareOptions();
+}
+
+template <>
+inline const circle::ZerosLikeOptions *
+Operator::builtin_options_as<circle::ZerosLikeOptions>() const
+{
+ return builtin_options_as_ZerosLikeOptions();
+}
+
+template <>
+inline const circle::FillOptions *Operator::builtin_options_as<circle::FillOptions>() const
+{
+ return builtin_options_as_FillOptions();
+}
+
+template <>
+inline const circle::BidirectionalSequenceLSTMOptions *
+Operator::builtin_options_as<circle::BidirectionalSequenceLSTMOptions>() const
+{
+ return builtin_options_as_BidirectionalSequenceLSTMOptions();
+}
+
+template <>
+inline const circle::BidirectionalSequenceRNNOptions *
+Operator::builtin_options_as<circle::BidirectionalSequenceRNNOptions>() const
+{
+ return builtin_options_as_BidirectionalSequenceRNNOptions();
+}
+
+template <>
+inline const circle::UnidirectionalSequenceLSTMOptions *
+Operator::builtin_options_as<circle::UnidirectionalSequenceLSTMOptions>() const
+{
+ return builtin_options_as_UnidirectionalSequenceLSTMOptions();
+}
+
+template <>
+inline const circle::FloorModOptions *Operator::builtin_options_as<circle::FloorModOptions>() const
+{
+ return builtin_options_as_FloorModOptions();
+}
+
+template <>
+inline const circle::RangeOptions *Operator::builtin_options_as<circle::RangeOptions>() const
+{
+ return builtin_options_as_RangeOptions();
+}
+
+template <>
+inline const circle::ResizeNearestNeighborOptions *
+Operator::builtin_options_as<circle::ResizeNearestNeighborOptions>() const
+{
+ return builtin_options_as_ResizeNearestNeighborOptions();
+}
+
+template <>
+inline const circle::LeakyReluOptions *
+Operator::builtin_options_as<circle::LeakyReluOptions>() const
+{
+ return builtin_options_as_LeakyReluOptions();
+}
+
+template <>
+inline const circle::SquaredDifferenceOptions *
+Operator::builtin_options_as<circle::SquaredDifferenceOptions>() const
+{
+ return builtin_options_as_SquaredDifferenceOptions();
+}
+
+template <>
+inline const circle::MirrorPadOptions *
+Operator::builtin_options_as<circle::MirrorPadOptions>() const
+{
+ return builtin_options_as_MirrorPadOptions();
+}
+
+template <>
+inline const circle::AbsOptions *Operator::builtin_options_as<circle::AbsOptions>() const
+{
+ return builtin_options_as_AbsOptions();
+}
+
+template <>
+inline const circle::SplitVOptions *Operator::builtin_options_as<circle::SplitVOptions>() const
+{
+ return builtin_options_as_SplitVOptions();
+}
+
+template <>
+inline const circle::UniqueOptions *Operator::builtin_options_as<circle::UniqueOptions>() const
+{
+ return builtin_options_as_UniqueOptions();
+}
+
+template <>
+inline const circle::ReverseV2Options *
+Operator::builtin_options_as<circle::ReverseV2Options>() const
+{
+ return builtin_options_as_ReverseV2Options();
+}
+
+template <>
+inline const circle::AddNOptions *Operator::builtin_options_as<circle::AddNOptions>() const
+{
+ return builtin_options_as_AddNOptions();
+}
+
+template <>
+inline const circle::GatherNdOptions *Operator::builtin_options_as<circle::GatherNdOptions>() const
+{
+ return builtin_options_as_GatherNdOptions();
+}
+
+template <>
+inline const circle::CosOptions *Operator::builtin_options_as<circle::CosOptions>() const
+{
+ return builtin_options_as_CosOptions();
+}
+
+template <>
+inline const circle::WhereOptions *Operator::builtin_options_as<circle::WhereOptions>() const
+{
+ return builtin_options_as_WhereOptions();
+}
+
+template <>
+inline const circle::RankOptions *Operator::builtin_options_as<circle::RankOptions>() const
+{
+ return builtin_options_as_RankOptions();
+}
+
+template <>
+inline const circle::ReverseSequenceOptions *
+Operator::builtin_options_as<circle::ReverseSequenceOptions>() const
+{
+ return builtin_options_as_ReverseSequenceOptions();
+}
+
+template <>
+inline const circle::MatrixDiagOptions *
+Operator::builtin_options_as<circle::MatrixDiagOptions>() const
+{
+ return builtin_options_as_MatrixDiagOptions();
+}
+
+template <>
+inline const circle::QuantizeOptions *Operator::builtin_options_as<circle::QuantizeOptions>() const
+{
+ return builtin_options_as_QuantizeOptions();
+}
+
+template <>
+inline const circle::MatrixSetDiagOptions *
+Operator::builtin_options_as<circle::MatrixSetDiagOptions>() const
+{
+ return builtin_options_as_MatrixSetDiagOptions();
+}
+
+template <>
+inline const circle::HardSwishOptions *
+Operator::builtin_options_as<circle::HardSwishOptions>() const
+{
+ return builtin_options_as_HardSwishOptions();
+}
+
+template <> inline const circle::IfOptions *Operator::builtin_options_as<circle::IfOptions>() const
+{
+ return builtin_options_as_IfOptions();
+}
+
+template <>
+inline const circle::WhileOptions *Operator::builtin_options_as<circle::WhileOptions>() const
+{
+ return builtin_options_as_WhileOptions();
+}
+
+template <>
+inline const circle::DepthToSpaceOptions *
+Operator::builtin_options_as<circle::DepthToSpaceOptions>() const
+{
+ return builtin_options_as_DepthToSpaceOptions();
+}
+
+template <>
+inline const circle::NonMaxSuppressionV4Options *
+Operator::builtin_options_as<circle::NonMaxSuppressionV4Options>() const
+{
+ return builtin_options_as_NonMaxSuppressionV4Options();
+}
+
+template <>
+inline const circle::NonMaxSuppressionV5Options *
+Operator::builtin_options_as<circle::NonMaxSuppressionV5Options>() const
+{
+ return builtin_options_as_NonMaxSuppressionV5Options();
+}
+
+template <>
+inline const circle::ScatterNdOptions *
+Operator::builtin_options_as<circle::ScatterNdOptions>() const
+{
+ return builtin_options_as_ScatterNdOptions();
+}
+
+template <>
+inline const circle::SelectV2Options *Operator::builtin_options_as<circle::SelectV2Options>() const
+{
+ return builtin_options_as_SelectV2Options();
+}
+
+template <>
+inline const circle::DensifyOptions *Operator::builtin_options_as<circle::DensifyOptions>() const
+{
+ return builtin_options_as_DensifyOptions();
+}
+
+template <>
+inline const circle::SegmentSumOptions *
+Operator::builtin_options_as<circle::SegmentSumOptions>() const
+{
+ return builtin_options_as_SegmentSumOptions();
+}
+
+template <>
+inline const circle::BatchMatMulOptions *
+Operator::builtin_options_as<circle::BatchMatMulOptions>() const
+{
+ return builtin_options_as_BatchMatMulOptions();
+}
+
+template <>
+inline const circle::CumsumOptions *Operator::builtin_options_as<circle::CumsumOptions>() const
+{
+ return builtin_options_as_CumsumOptions();
+}
+
+template <>
+inline const circle::CallOnceOptions *Operator::builtin_options_as<circle::CallOnceOptions>() const
+{
+ return builtin_options_as_CallOnceOptions();
+}
+
+template <>
+inline const circle::BroadcastToOptions *
+Operator::builtin_options_as<circle::BroadcastToOptions>() const
+{
+ return builtin_options_as_BroadcastToOptions();
+}
+
+template <>
+inline const circle::Rfft2dOptions *Operator::builtin_options_as<circle::Rfft2dOptions>() const
+{
+ return builtin_options_as_Rfft2dOptions();
+}
+
+template <>
+inline const circle::Conv3DOptions *Operator::builtin_options_as<circle::Conv3DOptions>() const
+{
+ return builtin_options_as_Conv3DOptions();
+}
+
+template <>
+inline const circle::HashtableOptions *
+Operator::builtin_options_as<circle::HashtableOptions>() const
+{
+ return builtin_options_as_HashtableOptions();
+}
+
+template <>
+inline const circle::HashtableFindOptions *
+Operator::builtin_options_as<circle::HashtableFindOptions>() const
+{
+ return builtin_options_as_HashtableFindOptions();
+}
+
+template <>
+inline const circle::HashtableImportOptions *
+Operator::builtin_options_as<circle::HashtableImportOptions>() const
+{
+ return builtin_options_as_HashtableImportOptions();
+}
+
+template <>
+inline const circle::HashtableSizeOptions *
+Operator::builtin_options_as<circle::HashtableSizeOptions>() const
+{
+ return builtin_options_as_HashtableSizeOptions();
+}
+
+template <>
+inline const circle::VarHandleOptions *
+Operator::builtin_options_as<circle::VarHandleOptions>() const
+{
+ return builtin_options_as_VarHandleOptions();
+}
+
+template <>
+inline const circle::ReadVariableOptions *
+Operator::builtin_options_as<circle::ReadVariableOptions>() const
+{
+ return builtin_options_as_ReadVariableOptions();
+}
+
+template <>
+inline const circle::AssignVariableOptions *
+Operator::builtin_options_as<circle::AssignVariableOptions>() const
+{
+ return builtin_options_as_AssignVariableOptions();
+}
+
+template <>
+inline const circle::RandomOptions *Operator::builtin_options_as<circle::RandomOptions>() const
+{
+ return builtin_options_as_RandomOptions();
+}
+
+template <>
+inline const circle::BCQGatherOptions *
+Operator::builtin_options_as<circle::BCQGatherOptions>() const
+{
+ return builtin_options_as_BCQGatherOptions();
+}
+
+template <>
+inline const circle::BCQFullyConnectedOptions *
+Operator::builtin_options_as<circle::BCQFullyConnectedOptions>() const
+{
+ return builtin_options_as_BCQFullyConnectedOptions();
+}
+
+template <>
+inline const circle::InstanceNormOptions *
+Operator::builtin_options_as<circle::InstanceNormOptions>() const
+{
+ return builtin_options_as_InstanceNormOptions();
+}
+
+struct OperatorBuilder
+{
+ typedef Operator Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_opcode_index(uint32_t opcode_index)
+ {
+ fbb_.AddElement<uint32_t>(Operator::VT_OPCODE_INDEX, opcode_index, 0);
+ }
+ void add_inputs(flatbuffers::Offset<flatbuffers::Vector<int32_t>> inputs)
+ {
+ fbb_.AddOffset(Operator::VT_INPUTS, inputs);
+ }
+ void add_outputs(flatbuffers::Offset<flatbuffers::Vector<int32_t>> outputs)
+ {
+ fbb_.AddOffset(Operator::VT_OUTPUTS, outputs);
+ }
+ void add_builtin_options_type(circle::BuiltinOptions builtin_options_type)
+ {
+ fbb_.AddElement<uint8_t>(Operator::VT_BUILTIN_OPTIONS_TYPE,
+ static_cast<uint8_t>(builtin_options_type), 0);
+ }
+ void add_builtin_options(flatbuffers::Offset<void> builtin_options)
+ {
+ fbb_.AddOffset(Operator::VT_BUILTIN_OPTIONS, builtin_options);
+ }
+ void add_custom_options(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> custom_options)
+ {
+ fbb_.AddOffset(Operator::VT_CUSTOM_OPTIONS, custom_options);
+ }
+ void add_custom_options_format(circle::CustomOptionsFormat custom_options_format)
+ {
+ fbb_.AddElement<int8_t>(Operator::VT_CUSTOM_OPTIONS_FORMAT,
+ static_cast<int8_t>(custom_options_format), 0);
+ }
+ void add_mutating_variable_inputs(
+ flatbuffers::Offset<flatbuffers::Vector<uint8_t>> mutating_variable_inputs)
+ {
+ fbb_.AddOffset(Operator::VT_MUTATING_VARIABLE_INPUTS, mutating_variable_inputs);
+ }
+ void add_intermediates(flatbuffers::Offset<flatbuffers::Vector<int32_t>> intermediates)
+ {
+ fbb_.AddOffset(Operator::VT_INTERMEDIATES, intermediates);
+ }
+ explicit OperatorBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<Operator> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Operator>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Operator> CreateOperator(
+ flatbuffers::FlatBufferBuilder &_fbb, uint32_t opcode_index = 0,
+ flatbuffers::Offset<flatbuffers::Vector<int32_t>> inputs = 0,
+ flatbuffers::Offset<flatbuffers::Vector<int32_t>> outputs = 0,
+ circle::BuiltinOptions builtin_options_type = circle::BuiltinOptions_NONE,
+ flatbuffers::Offset<void> builtin_options = 0,
+ flatbuffers::Offset<flatbuffers::Vector<uint8_t>> custom_options = 0,
+ circle::CustomOptionsFormat custom_options_format = circle::CustomOptionsFormat_FLEXBUFFERS,
+ flatbuffers::Offset<flatbuffers::Vector<uint8_t>> mutating_variable_inputs = 0,
+ flatbuffers::Offset<flatbuffers::Vector<int32_t>> intermediates = 0)
+{
+ OperatorBuilder builder_(_fbb);
+ builder_.add_intermediates(intermediates);
+ builder_.add_mutating_variable_inputs(mutating_variable_inputs);
+ builder_.add_custom_options(custom_options);
+ builder_.add_builtin_options(builtin_options);
+ builder_.add_outputs(outputs);
+ builder_.add_inputs(inputs);
+ builder_.add_opcode_index(opcode_index);
+ builder_.add_custom_options_format(custom_options_format);
+ builder_.add_builtin_options_type(builtin_options_type);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<Operator> CreateOperatorDirect(
+ flatbuffers::FlatBufferBuilder &_fbb, uint32_t opcode_index = 0,
+ const std::vector<int32_t> *inputs = nullptr, const std::vector<int32_t> *outputs = nullptr,
+ circle::BuiltinOptions builtin_options_type = circle::BuiltinOptions_NONE,
+ flatbuffers::Offset<void> builtin_options = 0,
+ const std::vector<uint8_t> *custom_options = nullptr,
+ circle::CustomOptionsFormat custom_options_format = circle::CustomOptionsFormat_FLEXBUFFERS,
+ const std::vector<uint8_t> *mutating_variable_inputs = nullptr,
+ const std::vector<int32_t> *intermediates = nullptr)
+{
+ auto inputs__ = inputs ? _fbb.CreateVector<int32_t>(*inputs) : 0;
+ auto outputs__ = outputs ? _fbb.CreateVector<int32_t>(*outputs) : 0;
+ auto custom_options__ = custom_options ? _fbb.CreateVector<uint8_t>(*custom_options) : 0;
+ auto mutating_variable_inputs__ =
+ mutating_variable_inputs ? _fbb.CreateVector<uint8_t>(*mutating_variable_inputs) : 0;
+ auto intermediates__ = intermediates ? _fbb.CreateVector<int32_t>(*intermediates) : 0;
+ return circle::CreateOperator(_fbb, opcode_index, inputs__, outputs__, builtin_options_type,
+ builtin_options, custom_options__, custom_options_format,
+ mutating_variable_inputs__, intermediates__);
+}
+
+flatbuffers::Offset<Operator>
+CreateOperator(flatbuffers::FlatBufferBuilder &_fbb, const OperatorT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct SubGraphT : public flatbuffers::NativeTable
+{
+ typedef SubGraph TableType;
+ std::vector<std::unique_ptr<circle::TensorT>> tensors{};
+ std::vector<int32_t> inputs{};
+ std::vector<int32_t> outputs{};
+ std::vector<std::unique_ptr<circle::OperatorT>> operators{};
+ std::string name{};
+ circle::DataFormat data_format = circle::DataFormat_CHANNELS_LAST;
+};
+
+struct SubGraph FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef SubGraphT NativeTableType;
+ typedef SubGraphBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_TENSORS = 4,
+ VT_INPUTS = 6,
+ VT_OUTPUTS = 8,
+ VT_OPERATORS = 10,
+ VT_NAME = 12,
+ VT_DATA_FORMAT = 14
+ };
+ const flatbuffers::Vector<flatbuffers::Offset<circle::Tensor>> *tensors() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<circle::Tensor>> *>(VT_TENSORS);
+ }
+ const flatbuffers::Vector<int32_t> *inputs() const
+ {
+ return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_INPUTS);
+ }
+ const flatbuffers::Vector<int32_t> *outputs() const
+ {
+ return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_OUTPUTS);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<circle::Operator>> *operators() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<circle::Operator>> *>(
+ VT_OPERATORS);
+ }
+ const flatbuffers::String *name() const
+ {
+ return GetPointer<const flatbuffers::String *>(VT_NAME);
+ }
+ circle::DataFormat data_format() const
+ {
+ return static_cast<circle::DataFormat>(GetField<int8_t>(VT_DATA_FORMAT, 0));
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_TENSORS) &&
+ verifier.VerifyVector(tensors()) && verifier.VerifyVectorOfTables(tensors()) &&
+ VerifyOffset(verifier, VT_INPUTS) && verifier.VerifyVector(inputs()) &&
+ VerifyOffset(verifier, VT_OUTPUTS) && verifier.VerifyVector(outputs()) &&
+ VerifyOffset(verifier, VT_OPERATORS) && verifier.VerifyVector(operators()) &&
+ verifier.VerifyVectorOfTables(operators()) && VerifyOffset(verifier, VT_NAME) &&
+ verifier.VerifyString(name()) && VerifyField<int8_t>(verifier, VT_DATA_FORMAT) &&
+ verifier.EndTable();
+ }
+ SubGraphT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(SubGraphT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<SubGraph>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const SubGraphT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct SubGraphBuilder
+{
+ typedef SubGraph Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void
+ add_tensors(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::Tensor>>> tensors)
+ {
+ fbb_.AddOffset(SubGraph::VT_TENSORS, tensors);
+ }
+ void add_inputs(flatbuffers::Offset<flatbuffers::Vector<int32_t>> inputs)
+ {
+ fbb_.AddOffset(SubGraph::VT_INPUTS, inputs);
+ }
+ void add_outputs(flatbuffers::Offset<flatbuffers::Vector<int32_t>> outputs)
+ {
+ fbb_.AddOffset(SubGraph::VT_OUTPUTS, outputs);
+ }
+ void add_operators(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::Operator>>> operators)
+ {
+ fbb_.AddOffset(SubGraph::VT_OPERATORS, operators);
+ }
+ void add_name(flatbuffers::Offset<flatbuffers::String> name)
+ {
+ fbb_.AddOffset(SubGraph::VT_NAME, name);
+ }
+ void add_data_format(circle::DataFormat data_format)
+ {
+ fbb_.AddElement<int8_t>(SubGraph::VT_DATA_FORMAT, static_cast<int8_t>(data_format), 0);
+ }
+ explicit SubGraphBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<SubGraph> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<SubGraph>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<SubGraph> CreateSubGraph(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::Tensor>>> tensors = 0,
+ flatbuffers::Offset<flatbuffers::Vector<int32_t>> inputs = 0,
+ flatbuffers::Offset<flatbuffers::Vector<int32_t>> outputs = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::Operator>>> operators = 0,
+ flatbuffers::Offset<flatbuffers::String> name = 0,
+ circle::DataFormat data_format = circle::DataFormat_CHANNELS_LAST)
+{
+ SubGraphBuilder builder_(_fbb);
+ builder_.add_name(name);
+ builder_.add_operators(operators);
+ builder_.add_outputs(outputs);
+ builder_.add_inputs(inputs);
+ builder_.add_tensors(tensors);
+ builder_.add_data_format(data_format);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<SubGraph> CreateSubGraphDirect(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ const std::vector<flatbuffers::Offset<circle::Tensor>> *tensors = nullptr,
+ const std::vector<int32_t> *inputs = nullptr, const std::vector<int32_t> *outputs = nullptr,
+ const std::vector<flatbuffers::Offset<circle::Operator>> *operators = nullptr,
+ const char *name = nullptr, circle::DataFormat data_format = circle::DataFormat_CHANNELS_LAST)
+{
+ auto tensors__ = tensors ? _fbb.CreateVector<flatbuffers::Offset<circle::Tensor>>(*tensors) : 0;
+ auto inputs__ = inputs ? _fbb.CreateVector<int32_t>(*inputs) : 0;
+ auto outputs__ = outputs ? _fbb.CreateVector<int32_t>(*outputs) : 0;
+ auto operators__ =
+ operators ? _fbb.CreateVector<flatbuffers::Offset<circle::Operator>>(*operators) : 0;
+ auto name__ = name ? _fbb.CreateString(name) : 0;
+ return circle::CreateSubGraph(_fbb, tensors__, inputs__, outputs__, operators__, name__,
+ data_format);
+}
+
+flatbuffers::Offset<SubGraph>
+CreateSubGraph(flatbuffers::FlatBufferBuilder &_fbb, const SubGraphT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct BufferT : public flatbuffers::NativeTable
+{
+ typedef Buffer TableType;
+ std::vector<uint8_t> data{};
+};
+
+struct Buffer FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef BufferT NativeTableType;
+ typedef BufferBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_DATA = 4
+ };
+ const flatbuffers::Vector<uint8_t> *data() const
+ {
+ return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_DATA);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_DATA) &&
+ verifier.VerifyVector(data()) && verifier.EndTable();
+ }
+ BufferT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(BufferT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<Buffer>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const BufferT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct BufferBuilder
+{
+ typedef Buffer Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_data(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> data)
+ {
+ fbb_.AddOffset(Buffer::VT_DATA, data);
+ }
+ explicit BufferBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<Buffer> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Buffer>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Buffer>
+CreateBuffer(flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::Vector<uint8_t>> data = 0)
+{
+ BufferBuilder builder_(_fbb);
+ builder_.add_data(data);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<Buffer> CreateBufferDirect(flatbuffers::FlatBufferBuilder &_fbb,
+ const std::vector<uint8_t> *data = nullptr)
+{
+ if (data)
+ {
+ _fbb.ForceVectorAlignment(data->size(), sizeof(uint8_t), 16);
+ }
+ auto data__ = data ? _fbb.CreateVector<uint8_t>(*data) : 0;
+ return circle::CreateBuffer(_fbb, data__);
+}
+
+flatbuffers::Offset<Buffer>
+CreateBuffer(flatbuffers::FlatBufferBuilder &_fbb, const BufferT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct MetadataT : public flatbuffers::NativeTable
+{
+ typedef Metadata TableType;
+ std::string name{};
+ uint32_t buffer = 0;
+};
+
+struct Metadata FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef MetadataT NativeTableType;
+ typedef MetadataBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_NAME = 4,
+ VT_BUFFER = 6
+ };
+ const flatbuffers::String *name() const
+ {
+ return GetPointer<const flatbuffers::String *>(VT_NAME);
+ }
+ uint32_t buffer() const { return GetField<uint32_t>(VT_BUFFER, 0); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_NAME) &&
+ verifier.VerifyString(name()) && VerifyField<uint32_t>(verifier, VT_BUFFER) &&
+ verifier.EndTable();
+ }
+ MetadataT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(MetadataT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<Metadata>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const MetadataT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct MetadataBuilder
+{
+ typedef Metadata Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_name(flatbuffers::Offset<flatbuffers::String> name)
+ {
+ fbb_.AddOffset(Metadata::VT_NAME, name);
+ }
+ void add_buffer(uint32_t buffer) { fbb_.AddElement<uint32_t>(Metadata::VT_BUFFER, buffer, 0); }
+ explicit MetadataBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<Metadata> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Metadata>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Metadata>
+CreateMetadata(flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::String> name = 0, uint32_t buffer = 0)
+{
+ MetadataBuilder builder_(_fbb);
+ builder_.add_buffer(buffer);
+ builder_.add_name(name);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<Metadata> CreateMetadataDirect(flatbuffers::FlatBufferBuilder &_fbb,
+ const char *name = nullptr,
+ uint32_t buffer = 0)
+{
+ auto name__ = name ? _fbb.CreateString(name) : 0;
+ return circle::CreateMetadata(_fbb, name__, buffer);
+}
+
+flatbuffers::Offset<Metadata>
+CreateMetadata(flatbuffers::FlatBufferBuilder &_fbb, const MetadataT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct TensorMapT : public flatbuffers::NativeTable
+{
+ typedef TensorMap TableType;
+ std::string name{};
+ uint32_t tensor_index = 0;
+};
+
+struct TensorMap FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef TensorMapT NativeTableType;
+ typedef TensorMapBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_NAME = 4,
+ VT_TENSOR_INDEX = 6
+ };
+ const flatbuffers::String *name() const
+ {
+ return GetPointer<const flatbuffers::String *>(VT_NAME);
+ }
+ uint32_t tensor_index() const { return GetField<uint32_t>(VT_TENSOR_INDEX, 0); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_NAME) &&
+ verifier.VerifyString(name()) && VerifyField<uint32_t>(verifier, VT_TENSOR_INDEX) &&
+ verifier.EndTable();
+ }
+ TensorMapT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(TensorMapT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<TensorMap>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const TensorMapT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct TensorMapBuilder
+{
+ typedef TensorMap Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_name(flatbuffers::Offset<flatbuffers::String> name)
+ {
+ fbb_.AddOffset(TensorMap::VT_NAME, name);
+ }
+ void add_tensor_index(uint32_t tensor_index)
+ {
+ fbb_.AddElement<uint32_t>(TensorMap::VT_TENSOR_INDEX, tensor_index, 0);
+ }
+ explicit TensorMapBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<TensorMap> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<TensorMap>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<TensorMap>
+CreateTensorMap(flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::String> name = 0, uint32_t tensor_index = 0)
+{
+ TensorMapBuilder builder_(_fbb);
+ builder_.add_tensor_index(tensor_index);
+ builder_.add_name(name);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<TensorMap> CreateTensorMapDirect(flatbuffers::FlatBufferBuilder &_fbb,
+ const char *name = nullptr,
+ uint32_t tensor_index = 0)
+{
+ auto name__ = name ? _fbb.CreateString(name) : 0;
+ return circle::CreateTensorMap(_fbb, name__, tensor_index);
+}
+
+flatbuffers::Offset<TensorMap>
+CreateTensorMap(flatbuffers::FlatBufferBuilder &_fbb, const TensorMapT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct SignatureDefT : public flatbuffers::NativeTable
+{
+ typedef SignatureDef TableType;
+ std::vector<std::unique_ptr<circle::TensorMapT>> inputs{};
+ std::vector<std::unique_ptr<circle::TensorMapT>> outputs{};
+ std::string signature_key{};
+ uint32_t subgraph_index = 0;
+};
+
+struct SignatureDef FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef SignatureDefT NativeTableType;
+ typedef SignatureDefBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_INPUTS = 4,
+ VT_OUTPUTS = 6,
+ VT_SIGNATURE_KEY = 8,
+ VT_SUBGRAPH_INDEX = 12
+ };
+ const flatbuffers::Vector<flatbuffers::Offset<circle::TensorMap>> *inputs() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<circle::TensorMap>> *>(
+ VT_INPUTS);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<circle::TensorMap>> *outputs() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<circle::TensorMap>> *>(
+ VT_OUTPUTS);
+ }
+ const flatbuffers::String *signature_key() const
+ {
+ return GetPointer<const flatbuffers::String *>(VT_SIGNATURE_KEY);
+ }
+ uint32_t subgraph_index() const { return GetField<uint32_t>(VT_SUBGRAPH_INDEX, 0); }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_INPUTS) &&
+ verifier.VerifyVector(inputs()) && verifier.VerifyVectorOfTables(inputs()) &&
+ VerifyOffset(verifier, VT_OUTPUTS) && verifier.VerifyVector(outputs()) &&
+ verifier.VerifyVectorOfTables(outputs()) && VerifyOffset(verifier, VT_SIGNATURE_KEY) &&
+ verifier.VerifyString(signature_key()) &&
+ VerifyField<uint32_t>(verifier, VT_SUBGRAPH_INDEX) && verifier.EndTable();
+ }
+ SignatureDefT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(SignatureDefT *_o,
+ const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<SignatureDef>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const SignatureDefT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct SignatureDefBuilder
+{
+ typedef SignatureDef Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_inputs(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::TensorMap>>> inputs)
+ {
+ fbb_.AddOffset(SignatureDef::VT_INPUTS, inputs);
+ }
+ void add_outputs(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::TensorMap>>> outputs)
+ {
+ fbb_.AddOffset(SignatureDef::VT_OUTPUTS, outputs);
+ }
+ void add_signature_key(flatbuffers::Offset<flatbuffers::String> signature_key)
+ {
+ fbb_.AddOffset(SignatureDef::VT_SIGNATURE_KEY, signature_key);
+ }
+ void add_subgraph_index(uint32_t subgraph_index)
+ {
+ fbb_.AddElement<uint32_t>(SignatureDef::VT_SUBGRAPH_INDEX, subgraph_index, 0);
+ }
+ explicit SignatureDefBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<SignatureDef> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<SignatureDef>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<SignatureDef> CreateSignatureDef(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::TensorMap>>> inputs = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::TensorMap>>> outputs = 0,
+ flatbuffers::Offset<flatbuffers::String> signature_key = 0, uint32_t subgraph_index = 0)
+{
+ SignatureDefBuilder builder_(_fbb);
+ builder_.add_subgraph_index(subgraph_index);
+ builder_.add_signature_key(signature_key);
+ builder_.add_outputs(outputs);
+ builder_.add_inputs(inputs);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<SignatureDef> CreateSignatureDefDirect(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ const std::vector<flatbuffers::Offset<circle::TensorMap>> *inputs = nullptr,
+ const std::vector<flatbuffers::Offset<circle::TensorMap>> *outputs = nullptr,
+ const char *signature_key = nullptr, uint32_t subgraph_index = 0)
+{
+ auto inputs__ = inputs ? _fbb.CreateVector<flatbuffers::Offset<circle::TensorMap>>(*inputs) : 0;
+ auto outputs__ =
+ outputs ? _fbb.CreateVector<flatbuffers::Offset<circle::TensorMap>>(*outputs) : 0;
+ auto signature_key__ = signature_key ? _fbb.CreateString(signature_key) : 0;
+ return circle::CreateSignatureDef(_fbb, inputs__, outputs__, signature_key__, subgraph_index);
+}
+
+flatbuffers::Offset<SignatureDef>
+CreateSignatureDef(flatbuffers::FlatBufferBuilder &_fbb, const SignatureDefT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct ModelT : public flatbuffers::NativeTable
+{
+ typedef Model TableType;
+ uint32_t version = 0;
+ std::vector<std::unique_ptr<circle::OperatorCodeT>> operator_codes{};
+ std::vector<std::unique_ptr<circle::SubGraphT>> subgraphs{};
+ std::string description{};
+ std::vector<std::unique_ptr<circle::BufferT>> buffers{};
+ std::vector<int32_t> metadata_buffer{};
+ std::vector<std::unique_ptr<circle::MetadataT>> metadata{};
+ std::vector<std::unique_ptr<circle::SignatureDefT>> signature_defs{};
+};
+
+struct Model FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef ModelT NativeTableType;
+ typedef ModelBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_VERSION = 4,
+ VT_OPERATOR_CODES = 6,
+ VT_SUBGRAPHS = 8,
+ VT_DESCRIPTION = 10,
+ VT_BUFFERS = 12,
+ VT_METADATA_BUFFER = 14,
+ VT_METADATA = 16,
+ VT_SIGNATURE_DEFS = 18
+ };
+ uint32_t version() const { return GetField<uint32_t>(VT_VERSION, 0); }
+ const flatbuffers::Vector<flatbuffers::Offset<circle::OperatorCode>> *operator_codes() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<circle::OperatorCode>> *>(
+ VT_OPERATOR_CODES);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<circle::SubGraph>> *subgraphs() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<circle::SubGraph>> *>(
+ VT_SUBGRAPHS);
+ }
+ const flatbuffers::String *description() const
+ {
+ return GetPointer<const flatbuffers::String *>(VT_DESCRIPTION);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<circle::Buffer>> *buffers() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<circle::Buffer>> *>(VT_BUFFERS);
+ }
+ const flatbuffers::Vector<int32_t> *metadata_buffer() const
+ {
+ return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_METADATA_BUFFER);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<circle::Metadata>> *metadata() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<circle::Metadata>> *>(
+ VT_METADATA);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<circle::SignatureDef>> *signature_defs() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<circle::SignatureDef>> *>(
+ VT_SIGNATURE_DEFS);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<uint32_t>(verifier, VT_VERSION) &&
+ VerifyOffset(verifier, VT_OPERATOR_CODES) && verifier.VerifyVector(operator_codes()) &&
+ verifier.VerifyVectorOfTables(operator_codes()) &&
+ VerifyOffset(verifier, VT_SUBGRAPHS) && verifier.VerifyVector(subgraphs()) &&
+ verifier.VerifyVectorOfTables(subgraphs()) && VerifyOffset(verifier, VT_DESCRIPTION) &&
+ verifier.VerifyString(description()) && VerifyOffset(verifier, VT_BUFFERS) &&
+ verifier.VerifyVector(buffers()) && verifier.VerifyVectorOfTables(buffers()) &&
+ VerifyOffset(verifier, VT_METADATA_BUFFER) && verifier.VerifyVector(metadata_buffer()) &&
+ VerifyOffset(verifier, VT_METADATA) && verifier.VerifyVector(metadata()) &&
+ verifier.VerifyVectorOfTables(metadata()) && VerifyOffset(verifier, VT_SIGNATURE_DEFS) &&
+ verifier.VerifyVector(signature_defs()) &&
+ verifier.VerifyVectorOfTables(signature_defs()) && verifier.EndTable();
+ }
+ ModelT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(ModelT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset<Model>
+ Pack(flatbuffers::FlatBufferBuilder &_fbb, const ModelT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct ModelBuilder
+{
+ typedef Model Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_version(uint32_t version) { fbb_.AddElement<uint32_t>(Model::VT_VERSION, version, 0); }
+ void add_operator_codes(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::OperatorCode>>>
+ operator_codes)
+ {
+ fbb_.AddOffset(Model::VT_OPERATOR_CODES, operator_codes);
+ }
+ void add_subgraphs(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::SubGraph>>> subgraphs)
+ {
+ fbb_.AddOffset(Model::VT_SUBGRAPHS, subgraphs);
+ }
+ void add_description(flatbuffers::Offset<flatbuffers::String> description)
+ {
+ fbb_.AddOffset(Model::VT_DESCRIPTION, description);
+ }
+ void
+ add_buffers(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::Buffer>>> buffers)
+ {
+ fbb_.AddOffset(Model::VT_BUFFERS, buffers);
+ }
+ void add_metadata_buffer(flatbuffers::Offset<flatbuffers::Vector<int32_t>> metadata_buffer)
+ {
+ fbb_.AddOffset(Model::VT_METADATA_BUFFER, metadata_buffer);
+ }
+ void add_metadata(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::Metadata>>> metadata)
+ {
+ fbb_.AddOffset(Model::VT_METADATA, metadata);
+ }
+ void add_signature_defs(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::SignatureDef>>>
+ signature_defs)
+ {
+ fbb_.AddOffset(Model::VT_SIGNATURE_DEFS, signature_defs);
+ }
+ explicit ModelBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<Model> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Model>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Model> CreateModel(
+ flatbuffers::FlatBufferBuilder &_fbb, uint32_t version = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::OperatorCode>>>
+ operator_codes = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::SubGraph>>> subgraphs = 0,
+ flatbuffers::Offset<flatbuffers::String> description = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::Buffer>>> buffers = 0,
+ flatbuffers::Offset<flatbuffers::Vector<int32_t>> metadata_buffer = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::Metadata>>> metadata = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::SignatureDef>>>
+ signature_defs = 0)
+{
+ ModelBuilder builder_(_fbb);
+ builder_.add_signature_defs(signature_defs);
+ builder_.add_metadata(metadata);
+ builder_.add_metadata_buffer(metadata_buffer);
+ builder_.add_buffers(buffers);
+ builder_.add_description(description);
+ builder_.add_subgraphs(subgraphs);
+ builder_.add_operator_codes(operator_codes);
+ builder_.add_version(version);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<Model> CreateModelDirect(
+ flatbuffers::FlatBufferBuilder &_fbb, uint32_t version = 0,
+ const std::vector<flatbuffers::Offset<circle::OperatorCode>> *operator_codes = nullptr,
+ const std::vector<flatbuffers::Offset<circle::SubGraph>> *subgraphs = nullptr,
+ const char *description = nullptr,
+ const std::vector<flatbuffers::Offset<circle::Buffer>> *buffers = nullptr,
+ const std::vector<int32_t> *metadata_buffer = nullptr,
+ const std::vector<flatbuffers::Offset<circle::Metadata>> *metadata = nullptr,
+ const std::vector<flatbuffers::Offset<circle::SignatureDef>> *signature_defs = nullptr)
+{
+ auto operator_codes__ =
+ operator_codes ? _fbb.CreateVector<flatbuffers::Offset<circle::OperatorCode>>(*operator_codes)
+ : 0;
+ auto subgraphs__ =
+ subgraphs ? _fbb.CreateVector<flatbuffers::Offset<circle::SubGraph>>(*subgraphs) : 0;
+ auto description__ = description ? _fbb.CreateString(description) : 0;
+ auto buffers__ = buffers ? _fbb.CreateVector<flatbuffers::Offset<circle::Buffer>>(*buffers) : 0;
+ auto metadata_buffer__ = metadata_buffer ? _fbb.CreateVector<int32_t>(*metadata_buffer) : 0;
+ auto metadata__ =
+ metadata ? _fbb.CreateVector<flatbuffers::Offset<circle::Metadata>>(*metadata) : 0;
+ auto signature_defs__ =
+ signature_defs ? _fbb.CreateVector<flatbuffers::Offset<circle::SignatureDef>>(*signature_defs)
+ : 0;
+ return circle::CreateModel(_fbb, version, operator_codes__, subgraphs__, description__, buffers__,
+ metadata_buffer__, metadata__, signature_defs__);
+}
+
+flatbuffers::Offset<Model> CreateModel(flatbuffers::FlatBufferBuilder &_fbb, const ModelT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+inline CustomQuantizationT *
+CustomQuantization::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<CustomQuantizationT>(new CustomQuantizationT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void CustomQuantization::UnPackTo(CustomQuantizationT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = custom();
+ if (_e)
+ {
+ _o->custom.resize(_e->size());
+ std::copy(_e->begin(), _e->end(), _o->custom.begin());
+ }
+ }
+}
+
+inline flatbuffers::Offset<CustomQuantization>
+CustomQuantization::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CustomQuantizationT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateCustomQuantization(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<CustomQuantization>
+CreateCustomQuantization(flatbuffers::FlatBufferBuilder &_fbb, const CustomQuantizationT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const CustomQuantizationT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ _fbb.ForceVectorAlignment(_o->custom.size(), sizeof(uint8_t), 16);
+ auto _custom = _o->custom.size() ? _fbb.CreateVector(_o->custom) : 0;
+ return circle::CreateCustomQuantization(_fbb, _custom);
+}
+
+inline QuantizationParametersT *
+QuantizationParameters::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<QuantizationParametersT>(new QuantizationParametersT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void
+QuantizationParameters::UnPackTo(QuantizationParametersT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = min();
+ if (_e)
+ {
+ _o->min.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->min[_i] = _e->Get(_i);
+ }
+ }
+ }
+ {
+ auto _e = max();
+ if (_e)
+ {
+ _o->max.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->max[_i] = _e->Get(_i);
+ }
+ }
+ }
+ {
+ auto _e = scale();
+ if (_e)
+ {
+ _o->scale.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->scale[_i] = _e->Get(_i);
+ }
+ }
+ }
+ {
+ auto _e = zero_point();
+ if (_e)
+ {
+ _o->zero_point.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->zero_point[_i] = _e->Get(_i);
+ }
+ }
+ }
+ {
+ auto _e = details_type();
+ _o->details.type = _e;
+ }
+ {
+ auto _e = details();
+ if (_e)
+ _o->details.value = circle::QuantizationDetailsUnion::UnPack(_e, details_type(), _resolver);
+ }
+ {
+ auto _e = quantized_dimension();
+ _o->quantized_dimension = _e;
+ }
+}
+
+inline flatbuffers::Offset<QuantizationParameters>
+QuantizationParameters::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+ const QuantizationParametersT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateQuantizationParameters(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<QuantizationParameters>
+CreateQuantizationParameters(flatbuffers::FlatBufferBuilder &_fbb,
+ const QuantizationParametersT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const QuantizationParametersT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _min = _o->min.size() ? _fbb.CreateVector(_o->min) : 0;
+ auto _max = _o->max.size() ? _fbb.CreateVector(_o->max) : 0;
+ auto _scale = _o->scale.size() ? _fbb.CreateVector(_o->scale) : 0;
+ auto _zero_point = _o->zero_point.size() ? _fbb.CreateVector(_o->zero_point) : 0;
+ auto _details_type = _o->details.type;
+ auto _details = _o->details.Pack(_fbb);
+ auto _quantized_dimension = _o->quantized_dimension;
+ return circle::CreateQuantizationParameters(_fbb, _min, _max, _scale, _zero_point, _details_type,
+ _details, _quantized_dimension);
+}
+
+inline Int32VectorT *Int32Vector::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<Int32VectorT>(new Int32VectorT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void Int32Vector::UnPackTo(Int32VectorT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = values();
+ if (_e)
+ {
+ _o->values.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->values[_i] = _e->Get(_i);
+ }
+ }
+ }
+}
+
+inline flatbuffers::Offset<Int32Vector>
+Int32Vector::Pack(flatbuffers::FlatBufferBuilder &_fbb, const Int32VectorT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateInt32Vector(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<Int32Vector>
+CreateInt32Vector(flatbuffers::FlatBufferBuilder &_fbb, const Int32VectorT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const Int32VectorT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _values = _o->values.size() ? _fbb.CreateVector(_o->values) : 0;
+ return circle::CreateInt32Vector(_fbb, _values);
+}
+
+inline Uint16VectorT *Uint16Vector::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<Uint16VectorT>(new Uint16VectorT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void Uint16Vector::UnPackTo(Uint16VectorT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = values();
+ if (_e)
+ {
+ _o->values.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->values[_i] = _e->Get(_i);
+ }
+ }
+ }
+}
+
+inline flatbuffers::Offset<Uint16Vector>
+Uint16Vector::Pack(flatbuffers::FlatBufferBuilder &_fbb, const Uint16VectorT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateUint16Vector(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<Uint16Vector>
+CreateUint16Vector(flatbuffers::FlatBufferBuilder &_fbb, const Uint16VectorT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const Uint16VectorT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ _fbb.ForceVectorAlignment(_o->values.size(), sizeof(uint16_t), 4);
+ auto _values = _o->values.size() ? _fbb.CreateVector(_o->values) : 0;
+ return circle::CreateUint16Vector(_fbb, _values);
+}
+
+inline Uint8VectorT *Uint8Vector::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<Uint8VectorT>(new Uint8VectorT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void Uint8Vector::UnPackTo(Uint8VectorT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = values();
+ if (_e)
+ {
+ _o->values.resize(_e->size());
+ std::copy(_e->begin(), _e->end(), _o->values.begin());
+ }
+ }
+}
+
+inline flatbuffers::Offset<Uint8Vector>
+Uint8Vector::Pack(flatbuffers::FlatBufferBuilder &_fbb, const Uint8VectorT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateUint8Vector(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<Uint8Vector>
+CreateUint8Vector(flatbuffers::FlatBufferBuilder &_fbb, const Uint8VectorT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const Uint8VectorT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ _fbb.ForceVectorAlignment(_o->values.size(), sizeof(uint8_t), 4);
+ auto _values = _o->values.size() ? _fbb.CreateVector(_o->values) : 0;
+ return circle::CreateUint8Vector(_fbb, _values);
+}
+
+inline DimensionMetadataT *
+DimensionMetadata::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<DimensionMetadataT>(new DimensionMetadataT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void DimensionMetadata::UnPackTo(DimensionMetadataT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = format();
+ _o->format = _e;
+ }
+ {
+ auto _e = dense_size();
+ _o->dense_size = _e;
+ }
+ {
+ auto _e = array_segments_type();
+ _o->array_segments.type = _e;
+ }
+ {
+ auto _e = array_segments();
+ if (_e)
+ _o->array_segments.value =
+ circle::SparseIndexVectorUnion::UnPack(_e, array_segments_type(), _resolver);
+ }
+ {
+ auto _e = array_indices_type();
+ _o->array_indices.type = _e;
+ }
+ {
+ auto _e = array_indices();
+ if (_e)
+ _o->array_indices.value =
+ circle::SparseIndexVectorUnion::UnPack(_e, array_indices_type(), _resolver);
+ }
+}
+
+inline flatbuffers::Offset<DimensionMetadata>
+DimensionMetadata::Pack(flatbuffers::FlatBufferBuilder &_fbb, const DimensionMetadataT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateDimensionMetadata(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<DimensionMetadata>
+CreateDimensionMetadata(flatbuffers::FlatBufferBuilder &_fbb, const DimensionMetadataT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const DimensionMetadataT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _format = _o->format;
+ auto _dense_size = _o->dense_size;
+ auto _array_segments_type = _o->array_segments.type;
+ auto _array_segments = _o->array_segments.Pack(_fbb);
+ auto _array_indices_type = _o->array_indices.type;
+ auto _array_indices = _o->array_indices.Pack(_fbb);
+ return circle::CreateDimensionMetadata(_fbb, _format, _dense_size, _array_segments_type,
+ _array_segments, _array_indices_type, _array_indices);
+}
+
+inline SparsityParametersT *
+SparsityParameters::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<SparsityParametersT>(new SparsityParametersT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void SparsityParameters::UnPackTo(SparsityParametersT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = traversal_order();
+ if (_e)
+ {
+ _o->traversal_order.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->traversal_order[_i] = _e->Get(_i);
+ }
+ }
+ }
+ {
+ auto _e = block_map();
+ if (_e)
+ {
+ _o->block_map.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->block_map[_i] = _e->Get(_i);
+ }
+ }
+ }
+ {
+ auto _e = dim_metadata();
+ if (_e)
+ {
+ _o->dim_metadata.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->dim_metadata[_i] =
+ std::unique_ptr<circle::DimensionMetadataT>(_e->Get(_i)->UnPack(_resolver));
+ }
+ }
+ }
+}
+
+inline flatbuffers::Offset<SparsityParameters>
+SparsityParameters::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SparsityParametersT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateSparsityParameters(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<SparsityParameters>
+CreateSparsityParameters(flatbuffers::FlatBufferBuilder &_fbb, const SparsityParametersT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const SparsityParametersT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _traversal_order = _o->traversal_order.size() ? _fbb.CreateVector(_o->traversal_order) : 0;
+ auto _block_map = _o->block_map.size() ? _fbb.CreateVector(_o->block_map) : 0;
+ auto _dim_metadata = _o->dim_metadata.size()
+ ? _fbb.CreateVector<flatbuffers::Offset<circle::DimensionMetadata>>(
+ _o->dim_metadata.size(),
+ [](size_t i, _VectorArgs *__va) {
+ return CreateDimensionMetadata(
+ *__va->__fbb, __va->__o->dim_metadata[i].get(), __va->__rehasher);
+ },
+ &_va)
+ : 0;
+ return circle::CreateSparsityParameters(_fbb, _traversal_order, _block_map, _dim_metadata);
+}
+
+inline TensorT *Tensor::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<TensorT>(new TensorT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void Tensor::UnPackTo(TensorT *_o, const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = shape();
+ if (_e)
+ {
+ _o->shape.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->shape[_i] = _e->Get(_i);
+ }
+ }
+ }
+ {
+ auto _e = type();
+ _o->type = _e;
+ }
+ {
+ auto _e = buffer();
+ _o->buffer = _e;
+ }
+ {
+ auto _e = name();
+ if (_e)
+ _o->name = _e->str();
+ }
+ {
+ auto _e = quantization();
+ if (_e)
+ _o->quantization = std::unique_ptr<circle::QuantizationParametersT>(_e->UnPack(_resolver));
+ }
+ {
+ auto _e = is_variable();
+ _o->is_variable = _e;
+ }
+ {
+ auto _e = sparsity();
+ if (_e)
+ _o->sparsity = std::unique_ptr<circle::SparsityParametersT>(_e->UnPack(_resolver));
+ }
+ {
+ auto _e = shape_signature();
+ if (_e)
+ {
+ _o->shape_signature.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->shape_signature[_i] = _e->Get(_i);
+ }
+ }
+ }
+}
+
+inline flatbuffers::Offset<Tensor> Tensor::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+ const TensorT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateTensor(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<Tensor> CreateTensor(flatbuffers::FlatBufferBuilder &_fbb,
+ const TensorT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const TensorT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _shape = _o->shape.size() ? _fbb.CreateVector(_o->shape) : 0;
+ auto _type = _o->type;
+ auto _buffer = _o->buffer;
+ auto _name = _o->name.empty() ? 0 : _fbb.CreateString(_o->name);
+ auto _quantization =
+ _o->quantization ? CreateQuantizationParameters(_fbb, _o->quantization.get(), _rehasher) : 0;
+ auto _is_variable = _o->is_variable;
+ auto _sparsity = _o->sparsity ? CreateSparsityParameters(_fbb, _o->sparsity.get(), _rehasher) : 0;
+ auto _shape_signature = _o->shape_signature.size() ? _fbb.CreateVector(_o->shape_signature) : 0;
+ return circle::CreateTensor(_fbb, _shape, _type, _buffer, _name, _quantization, _is_variable,
+ _sparsity, _shape_signature);
+}
+
+inline Conv2DOptionsT *
+Conv2DOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<Conv2DOptionsT>(new Conv2DOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void Conv2DOptions::UnPackTo(Conv2DOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = padding();
+ _o->padding = _e;
+ }
+ {
+ auto _e = stride_w();
+ _o->stride_w = _e;
+ }
+ {
+ auto _e = stride_h();
+ _o->stride_h = _e;
+ }
+ {
+ auto _e = fused_activation_function();
+ _o->fused_activation_function = _e;
+ }
+ {
+ auto _e = dilation_w_factor();
+ _o->dilation_w_factor = _e;
+ }
+ {
+ auto _e = dilation_h_factor();
+ _o->dilation_h_factor = _e;
+ }
+}
+
+inline flatbuffers::Offset<Conv2DOptions>
+Conv2DOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const Conv2DOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateConv2DOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<Conv2DOptions>
+CreateConv2DOptions(flatbuffers::FlatBufferBuilder &_fbb, const Conv2DOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const Conv2DOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _padding = _o->padding;
+ auto _stride_w = _o->stride_w;
+ auto _stride_h = _o->stride_h;
+ auto _fused_activation_function = _o->fused_activation_function;
+ auto _dilation_w_factor = _o->dilation_w_factor;
+ auto _dilation_h_factor = _o->dilation_h_factor;
+ return circle::CreateConv2DOptions(_fbb, _padding, _stride_w, _stride_h,
+ _fused_activation_function, _dilation_w_factor,
+ _dilation_h_factor);
+}
+
+inline Conv3DOptionsT *
+Conv3DOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<Conv3DOptionsT>(new Conv3DOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void Conv3DOptions::UnPackTo(Conv3DOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = padding();
+ _o->padding = _e;
+ }
+ {
+ auto _e = stride_d();
+ _o->stride_d = _e;
+ }
+ {
+ auto _e = stride_w();
+ _o->stride_w = _e;
+ }
+ {
+ auto _e = stride_h();
+ _o->stride_h = _e;
+ }
+ {
+ auto _e = fused_activation_function();
+ _o->fused_activation_function = _e;
+ }
+ {
+ auto _e = dilation_d_factor();
+ _o->dilation_d_factor = _e;
+ }
+ {
+ auto _e = dilation_w_factor();
+ _o->dilation_w_factor = _e;
+ }
+ {
+ auto _e = dilation_h_factor();
+ _o->dilation_h_factor = _e;
+ }
+}
+
+inline flatbuffers::Offset<Conv3DOptions>
+Conv3DOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const Conv3DOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateConv3DOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<Conv3DOptions>
+CreateConv3DOptions(flatbuffers::FlatBufferBuilder &_fbb, const Conv3DOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const Conv3DOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _padding = _o->padding;
+ auto _stride_d = _o->stride_d;
+ auto _stride_w = _o->stride_w;
+ auto _stride_h = _o->stride_h;
+ auto _fused_activation_function = _o->fused_activation_function;
+ auto _dilation_d_factor = _o->dilation_d_factor;
+ auto _dilation_w_factor = _o->dilation_w_factor;
+ auto _dilation_h_factor = _o->dilation_h_factor;
+ return circle::CreateConv3DOptions(_fbb, _padding, _stride_d, _stride_w, _stride_h,
+ _fused_activation_function, _dilation_d_factor,
+ _dilation_w_factor, _dilation_h_factor);
+}
+
+inline Pool2DOptionsT *
+Pool2DOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<Pool2DOptionsT>(new Pool2DOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void Pool2DOptions::UnPackTo(Pool2DOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = padding();
+ _o->padding = _e;
+ }
+ {
+ auto _e = stride_w();
+ _o->stride_w = _e;
+ }
+ {
+ auto _e = stride_h();
+ _o->stride_h = _e;
+ }
+ {
+ auto _e = filter_width();
+ _o->filter_width = _e;
+ }
+ {
+ auto _e = filter_height();
+ _o->filter_height = _e;
+ }
+ {
+ auto _e = fused_activation_function();
+ _o->fused_activation_function = _e;
+ }
+}
+
+inline flatbuffers::Offset<Pool2DOptions>
+Pool2DOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const Pool2DOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreatePool2DOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<Pool2DOptions>
+CreatePool2DOptions(flatbuffers::FlatBufferBuilder &_fbb, const Pool2DOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const Pool2DOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _padding = _o->padding;
+ auto _stride_w = _o->stride_w;
+ auto _stride_h = _o->stride_h;
+ auto _filter_width = _o->filter_width;
+ auto _filter_height = _o->filter_height;
+ auto _fused_activation_function = _o->fused_activation_function;
+ return circle::CreatePool2DOptions(_fbb, _padding, _stride_w, _stride_h, _filter_width,
+ _filter_height, _fused_activation_function);
+}
+
+inline DepthwiseConv2DOptionsT *
+DepthwiseConv2DOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<DepthwiseConv2DOptionsT>(new DepthwiseConv2DOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void
+DepthwiseConv2DOptions::UnPackTo(DepthwiseConv2DOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = padding();
+ _o->padding = _e;
+ }
+ {
+ auto _e = stride_w();
+ _o->stride_w = _e;
+ }
+ {
+ auto _e = stride_h();
+ _o->stride_h = _e;
+ }
+ {
+ auto _e = depth_multiplier();
+ _o->depth_multiplier = _e;
+ }
+ {
+ auto _e = fused_activation_function();
+ _o->fused_activation_function = _e;
+ }
+ {
+ auto _e = dilation_w_factor();
+ _o->dilation_w_factor = _e;
+ }
+ {
+ auto _e = dilation_h_factor();
+ _o->dilation_h_factor = _e;
+ }
+}
+
+inline flatbuffers::Offset<DepthwiseConv2DOptions>
+DepthwiseConv2DOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+ const DepthwiseConv2DOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateDepthwiseConv2DOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<DepthwiseConv2DOptions>
+CreateDepthwiseConv2DOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ const DepthwiseConv2DOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const DepthwiseConv2DOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _padding = _o->padding;
+ auto _stride_w = _o->stride_w;
+ auto _stride_h = _o->stride_h;
+ auto _depth_multiplier = _o->depth_multiplier;
+ auto _fused_activation_function = _o->fused_activation_function;
+ auto _dilation_w_factor = _o->dilation_w_factor;
+ auto _dilation_h_factor = _o->dilation_h_factor;
+ return circle::CreateDepthwiseConv2DOptions(_fbb, _padding, _stride_w, _stride_h,
+ _depth_multiplier, _fused_activation_function,
+ _dilation_w_factor, _dilation_h_factor);
+}
+
+inline ConcatEmbeddingsOptionsT *
+ConcatEmbeddingsOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<ConcatEmbeddingsOptionsT>(new ConcatEmbeddingsOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void
+ConcatEmbeddingsOptions::UnPackTo(ConcatEmbeddingsOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = num_channels();
+ _o->num_channels = _e;
+ }
+ {
+ auto _e = num_columns_per_channel();
+ if (_e)
+ {
+ _o->num_columns_per_channel.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->num_columns_per_channel[_i] = _e->Get(_i);
+ }
+ }
+ }
+ {
+ auto _e = embedding_dim_per_channel();
+ if (_e)
+ {
+ _o->embedding_dim_per_channel.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->embedding_dim_per_channel[_i] = _e->Get(_i);
+ }
+ }
+ }
+}
+
+inline flatbuffers::Offset<ConcatEmbeddingsOptions>
+ConcatEmbeddingsOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+ const ConcatEmbeddingsOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateConcatEmbeddingsOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<ConcatEmbeddingsOptions>
+CreateConcatEmbeddingsOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ const ConcatEmbeddingsOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const ConcatEmbeddingsOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _num_channels = _o->num_channels;
+ auto _num_columns_per_channel =
+ _o->num_columns_per_channel.size() ? _fbb.CreateVector(_o->num_columns_per_channel) : 0;
+ auto _embedding_dim_per_channel =
+ _o->embedding_dim_per_channel.size() ? _fbb.CreateVector(_o->embedding_dim_per_channel) : 0;
+ return circle::CreateConcatEmbeddingsOptions(_fbb, _num_channels, _num_columns_per_channel,
+ _embedding_dim_per_channel);
+}
+
+inline LSHProjectionOptionsT *
+LSHProjectionOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<LSHProjectionOptionsT>(new LSHProjectionOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void LSHProjectionOptions::UnPackTo(LSHProjectionOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = type();
+ _o->type = _e;
+ }
+}
+
+inline flatbuffers::Offset<LSHProjectionOptions>
+LSHProjectionOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LSHProjectionOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateLSHProjectionOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<LSHProjectionOptions>
+CreateLSHProjectionOptions(flatbuffers::FlatBufferBuilder &_fbb, const LSHProjectionOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const LSHProjectionOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _type = _o->type;
+ return circle::CreateLSHProjectionOptions(_fbb, _type);
+}
+
+inline SVDFOptionsT *SVDFOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<SVDFOptionsT>(new SVDFOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void SVDFOptions::UnPackTo(SVDFOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = rank();
+ _o->rank = _e;
+ }
+ {
+ auto _e = fused_activation_function();
+ _o->fused_activation_function = _e;
+ }
+ {
+ auto _e = asymmetric_quantize_inputs();
+ _o->asymmetric_quantize_inputs = _e;
+ }
+}
+
+inline flatbuffers::Offset<SVDFOptions>
+SVDFOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SVDFOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateSVDFOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<SVDFOptions>
+CreateSVDFOptions(flatbuffers::FlatBufferBuilder &_fbb, const SVDFOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const SVDFOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _rank = _o->rank;
+ auto _fused_activation_function = _o->fused_activation_function;
+ auto _asymmetric_quantize_inputs = _o->asymmetric_quantize_inputs;
+ return circle::CreateSVDFOptions(_fbb, _rank, _fused_activation_function,
+ _asymmetric_quantize_inputs);
+}
+
+inline RNNOptionsT *RNNOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<RNNOptionsT>(new RNNOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void RNNOptions::UnPackTo(RNNOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = fused_activation_function();
+ _o->fused_activation_function = _e;
+ }
+ {
+ auto _e = asymmetric_quantize_inputs();
+ _o->asymmetric_quantize_inputs = _e;
+ }
+}
+
+inline flatbuffers::Offset<RNNOptions>
+RNNOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const RNNOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateRNNOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<RNNOptions>
+CreateRNNOptions(flatbuffers::FlatBufferBuilder &_fbb, const RNNOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const RNNOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _fused_activation_function = _o->fused_activation_function;
+ auto _asymmetric_quantize_inputs = _o->asymmetric_quantize_inputs;
+ return circle::CreateRNNOptions(_fbb, _fused_activation_function, _asymmetric_quantize_inputs);
+}
+
+inline SequenceRNNOptionsT *
+SequenceRNNOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<SequenceRNNOptionsT>(new SequenceRNNOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void SequenceRNNOptions::UnPackTo(SequenceRNNOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = time_major();
+ _o->time_major = _e;
+ }
+ {
+ auto _e = fused_activation_function();
+ _o->fused_activation_function = _e;
+ }
+ {
+ auto _e = asymmetric_quantize_inputs();
+ _o->asymmetric_quantize_inputs = _e;
+ }
+}
+
+inline flatbuffers::Offset<SequenceRNNOptions>
+SequenceRNNOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SequenceRNNOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateSequenceRNNOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<SequenceRNNOptions>
+CreateSequenceRNNOptions(flatbuffers::FlatBufferBuilder &_fbb, const SequenceRNNOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const SequenceRNNOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _time_major = _o->time_major;
+ auto _fused_activation_function = _o->fused_activation_function;
+ auto _asymmetric_quantize_inputs = _o->asymmetric_quantize_inputs;
+ return circle::CreateSequenceRNNOptions(_fbb, _time_major, _fused_activation_function,
+ _asymmetric_quantize_inputs);
+}
+
+inline BidirectionalSequenceRNNOptionsT *
+BidirectionalSequenceRNNOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o =
+ std::unique_ptr<BidirectionalSequenceRNNOptionsT>(new BidirectionalSequenceRNNOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void
+BidirectionalSequenceRNNOptions::UnPackTo(BidirectionalSequenceRNNOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = time_major();
+ _o->time_major = _e;
+ }
+ {
+ auto _e = fused_activation_function();
+ _o->fused_activation_function = _e;
+ }
+ {
+ auto _e = merge_outputs();
+ _o->merge_outputs = _e;
+ }
+ {
+ auto _e = asymmetric_quantize_inputs();
+ _o->asymmetric_quantize_inputs = _e;
+ }
+}
+
+inline flatbuffers::Offset<BidirectionalSequenceRNNOptions>
+BidirectionalSequenceRNNOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+ const BidirectionalSequenceRNNOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateBidirectionalSequenceRNNOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<BidirectionalSequenceRNNOptions>
+CreateBidirectionalSequenceRNNOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ const BidirectionalSequenceRNNOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const BidirectionalSequenceRNNOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _time_major = _o->time_major;
+ auto _fused_activation_function = _o->fused_activation_function;
+ auto _merge_outputs = _o->merge_outputs;
+ auto _asymmetric_quantize_inputs = _o->asymmetric_quantize_inputs;
+ return circle::CreateBidirectionalSequenceRNNOptions(
+ _fbb, _time_major, _fused_activation_function, _merge_outputs, _asymmetric_quantize_inputs);
+}
+
+inline FullyConnectedOptionsT *
+FullyConnectedOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<FullyConnectedOptionsT>(new FullyConnectedOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void FullyConnectedOptions::UnPackTo(FullyConnectedOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = fused_activation_function();
+ _o->fused_activation_function = _e;
+ }
+ {
+ auto _e = weights_format();
+ _o->weights_format = _e;
+ }
+ {
+ auto _e = keep_num_dims();
+ _o->keep_num_dims = _e;
+ }
+ {
+ auto _e = asymmetric_quantize_inputs();
+ _o->asymmetric_quantize_inputs = _e;
+ }
+}
+
+inline flatbuffers::Offset<FullyConnectedOptions>
+FullyConnectedOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const FullyConnectedOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateFullyConnectedOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<FullyConnectedOptions>
+CreateFullyConnectedOptions(flatbuffers::FlatBufferBuilder &_fbb, const FullyConnectedOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const FullyConnectedOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _fused_activation_function = _o->fused_activation_function;
+ auto _weights_format = _o->weights_format;
+ auto _keep_num_dims = _o->keep_num_dims;
+ auto _asymmetric_quantize_inputs = _o->asymmetric_quantize_inputs;
+ return circle::CreateFullyConnectedOptions(_fbb, _fused_activation_function, _weights_format,
+ _keep_num_dims, _asymmetric_quantize_inputs);
+}
+
+inline SoftmaxOptionsT *
+SoftmaxOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<SoftmaxOptionsT>(new SoftmaxOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void SoftmaxOptions::UnPackTo(SoftmaxOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = beta();
+ _o->beta = _e;
+ }
+}
+
+inline flatbuffers::Offset<SoftmaxOptions>
+SoftmaxOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SoftmaxOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateSoftmaxOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<SoftmaxOptions>
+CreateSoftmaxOptions(flatbuffers::FlatBufferBuilder &_fbb, const SoftmaxOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const SoftmaxOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _beta = _o->beta;
+ return circle::CreateSoftmaxOptions(_fbb, _beta);
+}
+
+inline ConcatenationOptionsT *
+ConcatenationOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<ConcatenationOptionsT>(new ConcatenationOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void ConcatenationOptions::UnPackTo(ConcatenationOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = axis();
+ _o->axis = _e;
+ }
+ {
+ auto _e = fused_activation_function();
+ _o->fused_activation_function = _e;
+ }
+}
+
+inline flatbuffers::Offset<ConcatenationOptions>
+ConcatenationOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ConcatenationOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateConcatenationOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<ConcatenationOptions>
+CreateConcatenationOptions(flatbuffers::FlatBufferBuilder &_fbb, const ConcatenationOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const ConcatenationOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _axis = _o->axis;
+ auto _fused_activation_function = _o->fused_activation_function;
+ return circle::CreateConcatenationOptions(_fbb, _axis, _fused_activation_function);
+}
+
+inline AddOptionsT *AddOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<AddOptionsT>(new AddOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void AddOptions::UnPackTo(AddOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = fused_activation_function();
+ _o->fused_activation_function = _e;
+ }
+ {
+ auto _e = pot_scale_int16();
+ _o->pot_scale_int16 = _e;
+ }
+}
+
+inline flatbuffers::Offset<AddOptions>
+AddOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const AddOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateAddOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<AddOptions>
+CreateAddOptions(flatbuffers::FlatBufferBuilder &_fbb, const AddOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const AddOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _fused_activation_function = _o->fused_activation_function;
+ auto _pot_scale_int16 = _o->pot_scale_int16;
+ return circle::CreateAddOptions(_fbb, _fused_activation_function, _pot_scale_int16);
+}
+
+inline MulOptionsT *MulOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<MulOptionsT>(new MulOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void MulOptions::UnPackTo(MulOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = fused_activation_function();
+ _o->fused_activation_function = _e;
+ }
+}
+
+inline flatbuffers::Offset<MulOptions>
+MulOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MulOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateMulOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<MulOptions>
+CreateMulOptions(flatbuffers::FlatBufferBuilder &_fbb, const MulOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const MulOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _fused_activation_function = _o->fused_activation_function;
+ return circle::CreateMulOptions(_fbb, _fused_activation_function);
+}
+
+inline L2NormOptionsT *
+L2NormOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<L2NormOptionsT>(new L2NormOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void L2NormOptions::UnPackTo(L2NormOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = fused_activation_function();
+ _o->fused_activation_function = _e;
+ }
+}
+
+inline flatbuffers::Offset<L2NormOptions>
+L2NormOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const L2NormOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateL2NormOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<L2NormOptions>
+CreateL2NormOptions(flatbuffers::FlatBufferBuilder &_fbb, const L2NormOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const L2NormOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _fused_activation_function = _o->fused_activation_function;
+ return circle::CreateL2NormOptions(_fbb, _fused_activation_function);
+}
+
+inline LocalResponseNormalizationOptionsT *
+LocalResponseNormalizationOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o =
+ std::unique_ptr<LocalResponseNormalizationOptionsT>(new LocalResponseNormalizationOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void
+LocalResponseNormalizationOptions::UnPackTo(LocalResponseNormalizationOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = radius();
+ _o->radius = _e;
+ }
+ {
+ auto _e = bias();
+ _o->bias = _e;
+ }
+ {
+ auto _e = alpha();
+ _o->alpha = _e;
+ }
+ {
+ auto _e = beta();
+ _o->beta = _e;
+ }
+}
+
+inline flatbuffers::Offset<LocalResponseNormalizationOptions>
+LocalResponseNormalizationOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+ const LocalResponseNormalizationOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateLocalResponseNormalizationOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<LocalResponseNormalizationOptions>
+CreateLocalResponseNormalizationOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ const LocalResponseNormalizationOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const LocalResponseNormalizationOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _radius = _o->radius;
+ auto _bias = _o->bias;
+ auto _alpha = _o->alpha;
+ auto _beta = _o->beta;
+ return circle::CreateLocalResponseNormalizationOptions(_fbb, _radius, _bias, _alpha, _beta);
+}
+
+inline LSTMOptionsT *LSTMOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<LSTMOptionsT>(new LSTMOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void LSTMOptions::UnPackTo(LSTMOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = fused_activation_function();
+ _o->fused_activation_function = _e;
+ }
+ {
+ auto _e = cell_clip();
+ _o->cell_clip = _e;
+ }
+ {
+ auto _e = proj_clip();
+ _o->proj_clip = _e;
+ }
+ {
+ auto _e = kernel_type();
+ _o->kernel_type = _e;
+ }
+ {
+ auto _e = asymmetric_quantize_inputs();
+ _o->asymmetric_quantize_inputs = _e;
+ }
+}
+
+inline flatbuffers::Offset<LSTMOptions>
+LSTMOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LSTMOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateLSTMOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<LSTMOptions>
+CreateLSTMOptions(flatbuffers::FlatBufferBuilder &_fbb, const LSTMOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const LSTMOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _fused_activation_function = _o->fused_activation_function;
+ auto _cell_clip = _o->cell_clip;
+ auto _proj_clip = _o->proj_clip;
+ auto _kernel_type = _o->kernel_type;
+ auto _asymmetric_quantize_inputs = _o->asymmetric_quantize_inputs;
+ return circle::CreateLSTMOptions(_fbb, _fused_activation_function, _cell_clip, _proj_clip,
+ _kernel_type, _asymmetric_quantize_inputs);
+}
+
+inline UnidirectionalSequenceLSTMOptionsT *
+UnidirectionalSequenceLSTMOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o =
+ std::unique_ptr<UnidirectionalSequenceLSTMOptionsT>(new UnidirectionalSequenceLSTMOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void
+UnidirectionalSequenceLSTMOptions::UnPackTo(UnidirectionalSequenceLSTMOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = fused_activation_function();
+ _o->fused_activation_function = _e;
+ }
+ {
+ auto _e = cell_clip();
+ _o->cell_clip = _e;
+ }
+ {
+ auto _e = proj_clip();
+ _o->proj_clip = _e;
+ }
+ {
+ auto _e = time_major();
+ _o->time_major = _e;
+ }
+ {
+ auto _e = asymmetric_quantize_inputs();
+ _o->asymmetric_quantize_inputs = _e;
+ }
+}
+
+inline flatbuffers::Offset<UnidirectionalSequenceLSTMOptions>
+UnidirectionalSequenceLSTMOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+ const UnidirectionalSequenceLSTMOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateUnidirectionalSequenceLSTMOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<UnidirectionalSequenceLSTMOptions>
+CreateUnidirectionalSequenceLSTMOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ const UnidirectionalSequenceLSTMOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const UnidirectionalSequenceLSTMOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _fused_activation_function = _o->fused_activation_function;
+ auto _cell_clip = _o->cell_clip;
+ auto _proj_clip = _o->proj_clip;
+ auto _time_major = _o->time_major;
+ auto _asymmetric_quantize_inputs = _o->asymmetric_quantize_inputs;
+ return circle::CreateUnidirectionalSequenceLSTMOptions(_fbb, _fused_activation_function,
+ _cell_clip, _proj_clip, _time_major,
+ _asymmetric_quantize_inputs);
+}
+
+inline BidirectionalSequenceLSTMOptionsT *
+BidirectionalSequenceLSTMOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o =
+ std::unique_ptr<BidirectionalSequenceLSTMOptionsT>(new BidirectionalSequenceLSTMOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void
+BidirectionalSequenceLSTMOptions::UnPackTo(BidirectionalSequenceLSTMOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = fused_activation_function();
+ _o->fused_activation_function = _e;
+ }
+ {
+ auto _e = cell_clip();
+ _o->cell_clip = _e;
+ }
+ {
+ auto _e = proj_clip();
+ _o->proj_clip = _e;
+ }
+ {
+ auto _e = merge_outputs();
+ _o->merge_outputs = _e;
+ }
+ {
+ auto _e = time_major();
+ _o->time_major = _e;
+ }
+ {
+ auto _e = asymmetric_quantize_inputs();
+ _o->asymmetric_quantize_inputs = _e;
+ }
+}
+
+inline flatbuffers::Offset<BidirectionalSequenceLSTMOptions>
+BidirectionalSequenceLSTMOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+ const BidirectionalSequenceLSTMOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateBidirectionalSequenceLSTMOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<BidirectionalSequenceLSTMOptions>
+CreateBidirectionalSequenceLSTMOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ const BidirectionalSequenceLSTMOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const BidirectionalSequenceLSTMOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _fused_activation_function = _o->fused_activation_function;
+ auto _cell_clip = _o->cell_clip;
+ auto _proj_clip = _o->proj_clip;
+ auto _merge_outputs = _o->merge_outputs;
+ auto _time_major = _o->time_major;
+ auto _asymmetric_quantize_inputs = _o->asymmetric_quantize_inputs;
+ return circle::CreateBidirectionalSequenceLSTMOptions(_fbb, _fused_activation_function,
+ _cell_clip, _proj_clip, _merge_outputs,
+ _time_major, _asymmetric_quantize_inputs);
+}
+
+inline ResizeBilinearOptionsT *
+ResizeBilinearOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<ResizeBilinearOptionsT>(new ResizeBilinearOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void ResizeBilinearOptions::UnPackTo(ResizeBilinearOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = align_corners();
+ _o->align_corners = _e;
+ }
+ {
+ auto _e = half_pixel_centers();
+ _o->half_pixel_centers = _e;
+ }
+}
+
+inline flatbuffers::Offset<ResizeBilinearOptions>
+ResizeBilinearOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ResizeBilinearOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateResizeBilinearOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<ResizeBilinearOptions>
+CreateResizeBilinearOptions(flatbuffers::FlatBufferBuilder &_fbb, const ResizeBilinearOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const ResizeBilinearOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _align_corners = _o->align_corners;
+ auto _half_pixel_centers = _o->half_pixel_centers;
+ return circle::CreateResizeBilinearOptions(_fbb, _align_corners, _half_pixel_centers);
+}
+
+inline ResizeNearestNeighborOptionsT *
+ResizeNearestNeighborOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<ResizeNearestNeighborOptionsT>(new ResizeNearestNeighborOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void
+ResizeNearestNeighborOptions::UnPackTo(ResizeNearestNeighborOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = align_corners();
+ _o->align_corners = _e;
+ }
+ {
+ auto _e = half_pixel_centers();
+ _o->half_pixel_centers = _e;
+ }
+}
+
+inline flatbuffers::Offset<ResizeNearestNeighborOptions>
+ResizeNearestNeighborOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+ const ResizeNearestNeighborOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateResizeNearestNeighborOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<ResizeNearestNeighborOptions>
+CreateResizeNearestNeighborOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ const ResizeNearestNeighborOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const ResizeNearestNeighborOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _align_corners = _o->align_corners;
+ auto _half_pixel_centers = _o->half_pixel_centers;
+ return circle::CreateResizeNearestNeighborOptions(_fbb, _align_corners, _half_pixel_centers);
+}
+
+inline CallOptionsT *CallOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<CallOptionsT>(new CallOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void CallOptions::UnPackTo(CallOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = subgraph();
+ _o->subgraph = _e;
+ }
+}
+
+inline flatbuffers::Offset<CallOptions>
+CallOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CallOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateCallOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<CallOptions>
+CreateCallOptions(flatbuffers::FlatBufferBuilder &_fbb, const CallOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const CallOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _subgraph = _o->subgraph;
+ return circle::CreateCallOptions(_fbb, _subgraph);
+}
+
+inline PadOptionsT *PadOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<PadOptionsT>(new PadOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void PadOptions::UnPackTo(PadOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<PadOptions>
+PadOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const PadOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreatePadOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<PadOptions>
+CreatePadOptions(flatbuffers::FlatBufferBuilder &_fbb, const PadOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const PadOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreatePadOptions(_fbb);
+}
+
+inline PadV2OptionsT *PadV2Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<PadV2OptionsT>(new PadV2OptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void PadV2Options::UnPackTo(PadV2OptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<PadV2Options>
+PadV2Options::Pack(flatbuffers::FlatBufferBuilder &_fbb, const PadV2OptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreatePadV2Options(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<PadV2Options>
+CreatePadV2Options(flatbuffers::FlatBufferBuilder &_fbb, const PadV2OptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const PadV2OptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreatePadV2Options(_fbb);
+}
+
+inline ReshapeOptionsT *
+ReshapeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<ReshapeOptionsT>(new ReshapeOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void ReshapeOptions::UnPackTo(ReshapeOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = new_shape();
+ if (_e)
+ {
+ _o->new_shape.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->new_shape[_i] = _e->Get(_i);
+ }
+ }
+ }
+}
+
+inline flatbuffers::Offset<ReshapeOptions>
+ReshapeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ReshapeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateReshapeOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<ReshapeOptions>
+CreateReshapeOptions(flatbuffers::FlatBufferBuilder &_fbb, const ReshapeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const ReshapeOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _new_shape = _o->new_shape.size() ? _fbb.CreateVector(_o->new_shape) : 0;
+ return circle::CreateReshapeOptions(_fbb, _new_shape);
+}
+
+inline SpaceToBatchNDOptionsT *
+SpaceToBatchNDOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<SpaceToBatchNDOptionsT>(new SpaceToBatchNDOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void SpaceToBatchNDOptions::UnPackTo(SpaceToBatchNDOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<SpaceToBatchNDOptions>
+SpaceToBatchNDOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SpaceToBatchNDOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateSpaceToBatchNDOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<SpaceToBatchNDOptions>
+CreateSpaceToBatchNDOptions(flatbuffers::FlatBufferBuilder &_fbb, const SpaceToBatchNDOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const SpaceToBatchNDOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateSpaceToBatchNDOptions(_fbb);
+}
+
+inline BatchToSpaceNDOptionsT *
+BatchToSpaceNDOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<BatchToSpaceNDOptionsT>(new BatchToSpaceNDOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void BatchToSpaceNDOptions::UnPackTo(BatchToSpaceNDOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<BatchToSpaceNDOptions>
+BatchToSpaceNDOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const BatchToSpaceNDOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateBatchToSpaceNDOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<BatchToSpaceNDOptions>
+CreateBatchToSpaceNDOptions(flatbuffers::FlatBufferBuilder &_fbb, const BatchToSpaceNDOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const BatchToSpaceNDOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateBatchToSpaceNDOptions(_fbb);
+}
+
+inline SkipGramOptionsT *
+SkipGramOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<SkipGramOptionsT>(new SkipGramOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void SkipGramOptions::UnPackTo(SkipGramOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = ngram_size();
+ _o->ngram_size = _e;
+ }
+ {
+ auto _e = max_skip_size();
+ _o->max_skip_size = _e;
+ }
+ {
+ auto _e = include_all_ngrams();
+ _o->include_all_ngrams = _e;
+ }
+}
+
+inline flatbuffers::Offset<SkipGramOptions>
+SkipGramOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SkipGramOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateSkipGramOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<SkipGramOptions>
+CreateSkipGramOptions(flatbuffers::FlatBufferBuilder &_fbb, const SkipGramOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const SkipGramOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _ngram_size = _o->ngram_size;
+ auto _max_skip_size = _o->max_skip_size;
+ auto _include_all_ngrams = _o->include_all_ngrams;
+ return circle::CreateSkipGramOptions(_fbb, _ngram_size, _max_skip_size, _include_all_ngrams);
+}
+
+inline SpaceToDepthOptionsT *
+SpaceToDepthOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<SpaceToDepthOptionsT>(new SpaceToDepthOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void SpaceToDepthOptions::UnPackTo(SpaceToDepthOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = block_size();
+ _o->block_size = _e;
+ }
+}
+
+inline flatbuffers::Offset<SpaceToDepthOptions>
+SpaceToDepthOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SpaceToDepthOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateSpaceToDepthOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<SpaceToDepthOptions>
+CreateSpaceToDepthOptions(flatbuffers::FlatBufferBuilder &_fbb, const SpaceToDepthOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const SpaceToDepthOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _block_size = _o->block_size;
+ return circle::CreateSpaceToDepthOptions(_fbb, _block_size);
+}
+
+inline DepthToSpaceOptionsT *
+DepthToSpaceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<DepthToSpaceOptionsT>(new DepthToSpaceOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void DepthToSpaceOptions::UnPackTo(DepthToSpaceOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = block_size();
+ _o->block_size = _e;
+ }
+}
+
+inline flatbuffers::Offset<DepthToSpaceOptions>
+DepthToSpaceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const DepthToSpaceOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateDepthToSpaceOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<DepthToSpaceOptions>
+CreateDepthToSpaceOptions(flatbuffers::FlatBufferBuilder &_fbb, const DepthToSpaceOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const DepthToSpaceOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _block_size = _o->block_size;
+ return circle::CreateDepthToSpaceOptions(_fbb, _block_size);
+}
+
+inline SubOptionsT *SubOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<SubOptionsT>(new SubOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void SubOptions::UnPackTo(SubOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = fused_activation_function();
+ _o->fused_activation_function = _e;
+ }
+ {
+ auto _e = pot_scale_int16();
+ _o->pot_scale_int16 = _e;
+ }
+}
+
+inline flatbuffers::Offset<SubOptions>
+SubOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SubOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateSubOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<SubOptions>
+CreateSubOptions(flatbuffers::FlatBufferBuilder &_fbb, const SubOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const SubOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _fused_activation_function = _o->fused_activation_function;
+ auto _pot_scale_int16 = _o->pot_scale_int16;
+ return circle::CreateSubOptions(_fbb, _fused_activation_function, _pot_scale_int16);
+}
+
+inline DivOptionsT *DivOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<DivOptionsT>(new DivOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void DivOptions::UnPackTo(DivOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = fused_activation_function();
+ _o->fused_activation_function = _e;
+ }
+}
+
+inline flatbuffers::Offset<DivOptions>
+DivOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const DivOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateDivOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<DivOptions>
+CreateDivOptions(flatbuffers::FlatBufferBuilder &_fbb, const DivOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const DivOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _fused_activation_function = _o->fused_activation_function;
+ return circle::CreateDivOptions(_fbb, _fused_activation_function);
+}
+
+inline TopKV2OptionsT *
+TopKV2Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<TopKV2OptionsT>(new TopKV2OptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void TopKV2Options::UnPackTo(TopKV2OptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<TopKV2Options>
+TopKV2Options::Pack(flatbuffers::FlatBufferBuilder &_fbb, const TopKV2OptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateTopKV2Options(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<TopKV2Options>
+CreateTopKV2Options(flatbuffers::FlatBufferBuilder &_fbb, const TopKV2OptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const TopKV2OptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateTopKV2Options(_fbb);
+}
+
+inline EmbeddingLookupSparseOptionsT *
+EmbeddingLookupSparseOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<EmbeddingLookupSparseOptionsT>(new EmbeddingLookupSparseOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void
+EmbeddingLookupSparseOptions::UnPackTo(EmbeddingLookupSparseOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = combiner();
+ _o->combiner = _e;
+ }
+}
+
+inline flatbuffers::Offset<EmbeddingLookupSparseOptions>
+EmbeddingLookupSparseOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+ const EmbeddingLookupSparseOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateEmbeddingLookupSparseOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<EmbeddingLookupSparseOptions>
+CreateEmbeddingLookupSparseOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ const EmbeddingLookupSparseOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const EmbeddingLookupSparseOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _combiner = _o->combiner;
+ return circle::CreateEmbeddingLookupSparseOptions(_fbb, _combiner);
+}
+
+inline GatherOptionsT *
+GatherOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<GatherOptionsT>(new GatherOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void GatherOptions::UnPackTo(GatherOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = axis();
+ _o->axis = _e;
+ }
+ {
+ auto _e = batch_dims();
+ _o->batch_dims = _e;
+ }
+}
+
+inline flatbuffers::Offset<GatherOptions>
+GatherOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const GatherOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateGatherOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<GatherOptions>
+CreateGatherOptions(flatbuffers::FlatBufferBuilder &_fbb, const GatherOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const GatherOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _axis = _o->axis;
+ auto _batch_dims = _o->batch_dims;
+ return circle::CreateGatherOptions(_fbb, _axis, _batch_dims);
+}
+
+inline TransposeOptionsT *
+TransposeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<TransposeOptionsT>(new TransposeOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void TransposeOptions::UnPackTo(TransposeOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<TransposeOptions>
+TransposeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const TransposeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateTransposeOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<TransposeOptions>
+CreateTransposeOptions(flatbuffers::FlatBufferBuilder &_fbb, const TransposeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const TransposeOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateTransposeOptions(_fbb);
+}
+
+inline ExpOptionsT *ExpOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<ExpOptionsT>(new ExpOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void ExpOptions::UnPackTo(ExpOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<ExpOptions>
+ExpOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ExpOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateExpOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<ExpOptions>
+CreateExpOptions(flatbuffers::FlatBufferBuilder &_fbb, const ExpOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const ExpOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateExpOptions(_fbb);
+}
+
+inline CosOptionsT *CosOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<CosOptionsT>(new CosOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void CosOptions::UnPackTo(CosOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<CosOptions>
+CosOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CosOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateCosOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<CosOptions>
+CreateCosOptions(flatbuffers::FlatBufferBuilder &_fbb, const CosOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const CosOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateCosOptions(_fbb);
+}
+
+inline ReducerOptionsT *
+ReducerOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<ReducerOptionsT>(new ReducerOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void ReducerOptions::UnPackTo(ReducerOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = keep_dims();
+ _o->keep_dims = _e;
+ }
+}
+
+inline flatbuffers::Offset<ReducerOptions>
+ReducerOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ReducerOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateReducerOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<ReducerOptions>
+CreateReducerOptions(flatbuffers::FlatBufferBuilder &_fbb, const ReducerOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const ReducerOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _keep_dims = _o->keep_dims;
+ return circle::CreateReducerOptions(_fbb, _keep_dims);
+}
+
+inline SqueezeOptionsT *
+SqueezeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<SqueezeOptionsT>(new SqueezeOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void SqueezeOptions::UnPackTo(SqueezeOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = squeeze_dims();
+ if (_e)
+ {
+ _o->squeeze_dims.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->squeeze_dims[_i] = _e->Get(_i);
+ }
+ }
+ }
+}
+
+inline flatbuffers::Offset<SqueezeOptions>
+SqueezeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SqueezeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateSqueezeOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<SqueezeOptions>
+CreateSqueezeOptions(flatbuffers::FlatBufferBuilder &_fbb, const SqueezeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const SqueezeOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _squeeze_dims = _o->squeeze_dims.size() ? _fbb.CreateVector(_o->squeeze_dims) : 0;
+ return circle::CreateSqueezeOptions(_fbb, _squeeze_dims);
+}
+
+inline SplitOptionsT *SplitOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<SplitOptionsT>(new SplitOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void SplitOptions::UnPackTo(SplitOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = num_splits();
+ _o->num_splits = _e;
+ }
+}
+
+inline flatbuffers::Offset<SplitOptions>
+SplitOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SplitOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateSplitOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<SplitOptions>
+CreateSplitOptions(flatbuffers::FlatBufferBuilder &_fbb, const SplitOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const SplitOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _num_splits = _o->num_splits;
+ return circle::CreateSplitOptions(_fbb, _num_splits);
+}
+
+inline SplitVOptionsT *
+SplitVOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<SplitVOptionsT>(new SplitVOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void SplitVOptions::UnPackTo(SplitVOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = num_splits();
+ _o->num_splits = _e;
+ }
+}
+
+inline flatbuffers::Offset<SplitVOptions>
+SplitVOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SplitVOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateSplitVOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<SplitVOptions>
+CreateSplitVOptions(flatbuffers::FlatBufferBuilder &_fbb, const SplitVOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const SplitVOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _num_splits = _o->num_splits;
+ return circle::CreateSplitVOptions(_fbb, _num_splits);
+}
+
+inline StridedSliceOptionsT *
+StridedSliceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<StridedSliceOptionsT>(new StridedSliceOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void StridedSliceOptions::UnPackTo(StridedSliceOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = begin_mask();
+ _o->begin_mask = _e;
+ }
+ {
+ auto _e = end_mask();
+ _o->end_mask = _e;
+ }
+ {
+ auto _e = ellipsis_mask();
+ _o->ellipsis_mask = _e;
+ }
+ {
+ auto _e = new_axis_mask();
+ _o->new_axis_mask = _e;
+ }
+ {
+ auto _e = shrink_axis_mask();
+ _o->shrink_axis_mask = _e;
+ }
+}
+
+inline flatbuffers::Offset<StridedSliceOptions>
+StridedSliceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const StridedSliceOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateStridedSliceOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<StridedSliceOptions>
+CreateStridedSliceOptions(flatbuffers::FlatBufferBuilder &_fbb, const StridedSliceOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const StridedSliceOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _begin_mask = _o->begin_mask;
+ auto _end_mask = _o->end_mask;
+ auto _ellipsis_mask = _o->ellipsis_mask;
+ auto _new_axis_mask = _o->new_axis_mask;
+ auto _shrink_axis_mask = _o->shrink_axis_mask;
+ return circle::CreateStridedSliceOptions(_fbb, _begin_mask, _end_mask, _ellipsis_mask,
+ _new_axis_mask, _shrink_axis_mask);
+}
+
+inline LogSoftmaxOptionsT *
+LogSoftmaxOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<LogSoftmaxOptionsT>(new LogSoftmaxOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void LogSoftmaxOptions::UnPackTo(LogSoftmaxOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<LogSoftmaxOptions>
+LogSoftmaxOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LogSoftmaxOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateLogSoftmaxOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<LogSoftmaxOptions>
+CreateLogSoftmaxOptions(flatbuffers::FlatBufferBuilder &_fbb, const LogSoftmaxOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const LogSoftmaxOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateLogSoftmaxOptions(_fbb);
+}
+
+inline CastOptionsT *CastOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<CastOptionsT>(new CastOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void CastOptions::UnPackTo(CastOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = in_data_type();
+ _o->in_data_type = _e;
+ }
+ {
+ auto _e = out_data_type();
+ _o->out_data_type = _e;
+ }
+}
+
+inline flatbuffers::Offset<CastOptions>
+CastOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CastOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateCastOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<CastOptions>
+CreateCastOptions(flatbuffers::FlatBufferBuilder &_fbb, const CastOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const CastOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _in_data_type = _o->in_data_type;
+ auto _out_data_type = _o->out_data_type;
+ return circle::CreateCastOptions(_fbb, _in_data_type, _out_data_type);
+}
+
+inline DequantizeOptionsT *
+DequantizeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<DequantizeOptionsT>(new DequantizeOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void DequantizeOptions::UnPackTo(DequantizeOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<DequantizeOptions>
+DequantizeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const DequantizeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateDequantizeOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<DequantizeOptions>
+CreateDequantizeOptions(flatbuffers::FlatBufferBuilder &_fbb, const DequantizeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const DequantizeOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateDequantizeOptions(_fbb);
+}
+
+inline MaximumMinimumOptionsT *
+MaximumMinimumOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<MaximumMinimumOptionsT>(new MaximumMinimumOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void MaximumMinimumOptions::UnPackTo(MaximumMinimumOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<MaximumMinimumOptions>
+MaximumMinimumOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MaximumMinimumOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateMaximumMinimumOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<MaximumMinimumOptions>
+CreateMaximumMinimumOptions(flatbuffers::FlatBufferBuilder &_fbb, const MaximumMinimumOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const MaximumMinimumOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateMaximumMinimumOptions(_fbb);
+}
+
+inline TileOptionsT *TileOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<TileOptionsT>(new TileOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void TileOptions::UnPackTo(TileOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<TileOptions>
+TileOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const TileOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateTileOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<TileOptions>
+CreateTileOptions(flatbuffers::FlatBufferBuilder &_fbb, const TileOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const TileOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateTileOptions(_fbb);
+}
+
+inline ArgMaxOptionsT *
+ArgMaxOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<ArgMaxOptionsT>(new ArgMaxOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void ArgMaxOptions::UnPackTo(ArgMaxOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = output_type();
+ _o->output_type = _e;
+ }
+}
+
+inline flatbuffers::Offset<ArgMaxOptions>
+ArgMaxOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ArgMaxOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateArgMaxOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<ArgMaxOptions>
+CreateArgMaxOptions(flatbuffers::FlatBufferBuilder &_fbb, const ArgMaxOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const ArgMaxOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _output_type = _o->output_type;
+ return circle::CreateArgMaxOptions(_fbb, _output_type);
+}
+
+inline ArgMinOptionsT *
+ArgMinOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<ArgMinOptionsT>(new ArgMinOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void ArgMinOptions::UnPackTo(ArgMinOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = output_type();
+ _o->output_type = _e;
+ }
+}
+
+inline flatbuffers::Offset<ArgMinOptions>
+ArgMinOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ArgMinOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateArgMinOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<ArgMinOptions>
+CreateArgMinOptions(flatbuffers::FlatBufferBuilder &_fbb, const ArgMinOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const ArgMinOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _output_type = _o->output_type;
+ return circle::CreateArgMinOptions(_fbb, _output_type);
+}
+
+inline GreaterOptionsT *
+GreaterOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<GreaterOptionsT>(new GreaterOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void GreaterOptions::UnPackTo(GreaterOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<GreaterOptions>
+GreaterOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const GreaterOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateGreaterOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<GreaterOptions>
+CreateGreaterOptions(flatbuffers::FlatBufferBuilder &_fbb, const GreaterOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const GreaterOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateGreaterOptions(_fbb);
+}
+
+inline GreaterEqualOptionsT *
+GreaterEqualOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<GreaterEqualOptionsT>(new GreaterEqualOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void GreaterEqualOptions::UnPackTo(GreaterEqualOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<GreaterEqualOptions>
+GreaterEqualOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const GreaterEqualOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateGreaterEqualOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<GreaterEqualOptions>
+CreateGreaterEqualOptions(flatbuffers::FlatBufferBuilder &_fbb, const GreaterEqualOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const GreaterEqualOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateGreaterEqualOptions(_fbb);
+}
+
+inline LessOptionsT *LessOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<LessOptionsT>(new LessOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void LessOptions::UnPackTo(LessOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<LessOptions>
+LessOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LessOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateLessOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<LessOptions>
+CreateLessOptions(flatbuffers::FlatBufferBuilder &_fbb, const LessOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const LessOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateLessOptions(_fbb);
+}
+
+inline LessEqualOptionsT *
+LessEqualOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<LessEqualOptionsT>(new LessEqualOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void LessEqualOptions::UnPackTo(LessEqualOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<LessEqualOptions>
+LessEqualOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LessEqualOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateLessEqualOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<LessEqualOptions>
+CreateLessEqualOptions(flatbuffers::FlatBufferBuilder &_fbb, const LessEqualOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const LessEqualOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateLessEqualOptions(_fbb);
+}
+
+inline NegOptionsT *NegOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<NegOptionsT>(new NegOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void NegOptions::UnPackTo(NegOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<NegOptions>
+NegOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const NegOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateNegOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<NegOptions>
+CreateNegOptions(flatbuffers::FlatBufferBuilder &_fbb, const NegOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const NegOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateNegOptions(_fbb);
+}
+
+inline SelectOptionsT *
+SelectOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<SelectOptionsT>(new SelectOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void SelectOptions::UnPackTo(SelectOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<SelectOptions>
+SelectOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SelectOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateSelectOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<SelectOptions>
+CreateSelectOptions(flatbuffers::FlatBufferBuilder &_fbb, const SelectOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const SelectOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateSelectOptions(_fbb);
+}
+
+inline SliceOptionsT *SliceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<SliceOptionsT>(new SliceOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void SliceOptions::UnPackTo(SliceOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<SliceOptions>
+SliceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SliceOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateSliceOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<SliceOptions>
+CreateSliceOptions(flatbuffers::FlatBufferBuilder &_fbb, const SliceOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const SliceOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateSliceOptions(_fbb);
+}
+
+inline TransposeConvOptionsT *
+TransposeConvOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<TransposeConvOptionsT>(new TransposeConvOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void TransposeConvOptions::UnPackTo(TransposeConvOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = padding();
+ _o->padding = _e;
+ }
+ {
+ auto _e = stride_w();
+ _o->stride_w = _e;
+ }
+ {
+ auto _e = stride_h();
+ _o->stride_h = _e;
+ }
+}
+
+inline flatbuffers::Offset<TransposeConvOptions>
+TransposeConvOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const TransposeConvOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateTransposeConvOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<TransposeConvOptions>
+CreateTransposeConvOptions(flatbuffers::FlatBufferBuilder &_fbb, const TransposeConvOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const TransposeConvOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _padding = _o->padding;
+ auto _stride_w = _o->stride_w;
+ auto _stride_h = _o->stride_h;
+ return circle::CreateTransposeConvOptions(_fbb, _padding, _stride_w, _stride_h);
+}
+
+inline ExpandDimsOptionsT *
+ExpandDimsOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<ExpandDimsOptionsT>(new ExpandDimsOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void ExpandDimsOptions::UnPackTo(ExpandDimsOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<ExpandDimsOptions>
+ExpandDimsOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ExpandDimsOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateExpandDimsOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<ExpandDimsOptions>
+CreateExpandDimsOptions(flatbuffers::FlatBufferBuilder &_fbb, const ExpandDimsOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const ExpandDimsOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateExpandDimsOptions(_fbb);
+}
+
+inline SparseToDenseOptionsT *
+SparseToDenseOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<SparseToDenseOptionsT>(new SparseToDenseOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void SparseToDenseOptions::UnPackTo(SparseToDenseOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = validate_indices();
+ _o->validate_indices = _e;
+ }
+}
+
+inline flatbuffers::Offset<SparseToDenseOptions>
+SparseToDenseOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SparseToDenseOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateSparseToDenseOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<SparseToDenseOptions>
+CreateSparseToDenseOptions(flatbuffers::FlatBufferBuilder &_fbb, const SparseToDenseOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const SparseToDenseOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _validate_indices = _o->validate_indices;
+ return circle::CreateSparseToDenseOptions(_fbb, _validate_indices);
+}
+
+inline EqualOptionsT *EqualOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<EqualOptionsT>(new EqualOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void EqualOptions::UnPackTo(EqualOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<EqualOptions>
+EqualOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const EqualOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateEqualOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<EqualOptions>
+CreateEqualOptions(flatbuffers::FlatBufferBuilder &_fbb, const EqualOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const EqualOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateEqualOptions(_fbb);
+}
+
+inline NotEqualOptionsT *
+NotEqualOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<NotEqualOptionsT>(new NotEqualOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void NotEqualOptions::UnPackTo(NotEqualOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<NotEqualOptions>
+NotEqualOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const NotEqualOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateNotEqualOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<NotEqualOptions>
+CreateNotEqualOptions(flatbuffers::FlatBufferBuilder &_fbb, const NotEqualOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const NotEqualOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateNotEqualOptions(_fbb);
+}
+
+inline ShapeOptionsT *ShapeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<ShapeOptionsT>(new ShapeOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void ShapeOptions::UnPackTo(ShapeOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = out_type();
+ _o->out_type = _e;
+ }
+}
+
+inline flatbuffers::Offset<ShapeOptions>
+ShapeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ShapeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateShapeOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<ShapeOptions>
+CreateShapeOptions(flatbuffers::FlatBufferBuilder &_fbb, const ShapeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const ShapeOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _out_type = _o->out_type;
+ return circle::CreateShapeOptions(_fbb, _out_type);
+}
+
+inline RankOptionsT *RankOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<RankOptionsT>(new RankOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void RankOptions::UnPackTo(RankOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<RankOptions>
+RankOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const RankOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateRankOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<RankOptions>
+CreateRankOptions(flatbuffers::FlatBufferBuilder &_fbb, const RankOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const RankOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateRankOptions(_fbb);
+}
+
+inline PowOptionsT *PowOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<PowOptionsT>(new PowOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void PowOptions::UnPackTo(PowOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<PowOptions>
+PowOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const PowOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreatePowOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<PowOptions>
+CreatePowOptions(flatbuffers::FlatBufferBuilder &_fbb, const PowOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const PowOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreatePowOptions(_fbb);
+}
+
+inline FakeQuantOptionsT *
+FakeQuantOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<FakeQuantOptionsT>(new FakeQuantOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void FakeQuantOptions::UnPackTo(FakeQuantOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = min();
+ _o->min = _e;
+ }
+ {
+ auto _e = max();
+ _o->max = _e;
+ }
+ {
+ auto _e = num_bits();
+ _o->num_bits = _e;
+ }
+ {
+ auto _e = narrow_range();
+ _o->narrow_range = _e;
+ }
+}
+
+inline flatbuffers::Offset<FakeQuantOptions>
+FakeQuantOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const FakeQuantOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateFakeQuantOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<FakeQuantOptions>
+CreateFakeQuantOptions(flatbuffers::FlatBufferBuilder &_fbb, const FakeQuantOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const FakeQuantOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _min = _o->min;
+ auto _max = _o->max;
+ auto _num_bits = _o->num_bits;
+ auto _narrow_range = _o->narrow_range;
+ return circle::CreateFakeQuantOptions(_fbb, _min, _max, _num_bits, _narrow_range);
+}
+
+inline PackOptionsT *PackOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<PackOptionsT>(new PackOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void PackOptions::UnPackTo(PackOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = values_count();
+ _o->values_count = _e;
+ }
+ {
+ auto _e = axis();
+ _o->axis = _e;
+ }
+}
+
+inline flatbuffers::Offset<PackOptions>
+PackOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const PackOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreatePackOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<PackOptions>
+CreatePackOptions(flatbuffers::FlatBufferBuilder &_fbb, const PackOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const PackOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _values_count = _o->values_count;
+ auto _axis = _o->axis;
+ return circle::CreatePackOptions(_fbb, _values_count, _axis);
+}
+
+inline LogicalOrOptionsT *
+LogicalOrOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<LogicalOrOptionsT>(new LogicalOrOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void LogicalOrOptions::UnPackTo(LogicalOrOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<LogicalOrOptions>
+LogicalOrOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LogicalOrOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateLogicalOrOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<LogicalOrOptions>
+CreateLogicalOrOptions(flatbuffers::FlatBufferBuilder &_fbb, const LogicalOrOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const LogicalOrOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateLogicalOrOptions(_fbb);
+}
+
+inline OneHotOptionsT *
+OneHotOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<OneHotOptionsT>(new OneHotOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void OneHotOptions::UnPackTo(OneHotOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = axis();
+ _o->axis = _e;
+ }
+}
+
+inline flatbuffers::Offset<OneHotOptions>
+OneHotOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const OneHotOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateOneHotOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<OneHotOptions>
+CreateOneHotOptions(flatbuffers::FlatBufferBuilder &_fbb, const OneHotOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const OneHotOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _axis = _o->axis;
+ return circle::CreateOneHotOptions(_fbb, _axis);
+}
+
+inline AbsOptionsT *AbsOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<AbsOptionsT>(new AbsOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void AbsOptions::UnPackTo(AbsOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<AbsOptions>
+AbsOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const AbsOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateAbsOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<AbsOptions>
+CreateAbsOptions(flatbuffers::FlatBufferBuilder &_fbb, const AbsOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const AbsOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateAbsOptions(_fbb);
+}
+
+inline HardSwishOptionsT *
+HardSwishOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<HardSwishOptionsT>(new HardSwishOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void HardSwishOptions::UnPackTo(HardSwishOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<HardSwishOptions>
+HardSwishOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const HardSwishOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateHardSwishOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<HardSwishOptions>
+CreateHardSwishOptions(flatbuffers::FlatBufferBuilder &_fbb, const HardSwishOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const HardSwishOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateHardSwishOptions(_fbb);
+}
+
+inline LogicalAndOptionsT *
+LogicalAndOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<LogicalAndOptionsT>(new LogicalAndOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void LogicalAndOptions::UnPackTo(LogicalAndOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<LogicalAndOptions>
+LogicalAndOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LogicalAndOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateLogicalAndOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<LogicalAndOptions>
+CreateLogicalAndOptions(flatbuffers::FlatBufferBuilder &_fbb, const LogicalAndOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const LogicalAndOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateLogicalAndOptions(_fbb);
+}
+
+inline LogicalNotOptionsT *
+LogicalNotOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<LogicalNotOptionsT>(new LogicalNotOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void LogicalNotOptions::UnPackTo(LogicalNotOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<LogicalNotOptions>
+LogicalNotOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LogicalNotOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateLogicalNotOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<LogicalNotOptions>
+CreateLogicalNotOptions(flatbuffers::FlatBufferBuilder &_fbb, const LogicalNotOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const LogicalNotOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateLogicalNotOptions(_fbb);
+}
+
+inline UnpackOptionsT *
+UnpackOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<UnpackOptionsT>(new UnpackOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void UnpackOptions::UnPackTo(UnpackOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = num();
+ _o->num = _e;
+ }
+ {
+ auto _e = axis();
+ _o->axis = _e;
+ }
+}
+
+inline flatbuffers::Offset<UnpackOptions>
+UnpackOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const UnpackOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateUnpackOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<UnpackOptions>
+CreateUnpackOptions(flatbuffers::FlatBufferBuilder &_fbb, const UnpackOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const UnpackOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _num = _o->num;
+ auto _axis = _o->axis;
+ return circle::CreateUnpackOptions(_fbb, _num, _axis);
+}
+
+inline FloorDivOptionsT *
+FloorDivOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<FloorDivOptionsT>(new FloorDivOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void FloorDivOptions::UnPackTo(FloorDivOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<FloorDivOptions>
+FloorDivOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const FloorDivOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateFloorDivOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<FloorDivOptions>
+CreateFloorDivOptions(flatbuffers::FlatBufferBuilder &_fbb, const FloorDivOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const FloorDivOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateFloorDivOptions(_fbb);
+}
+
+inline SquareOptionsT *
+SquareOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<SquareOptionsT>(new SquareOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void SquareOptions::UnPackTo(SquareOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<SquareOptions>
+SquareOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SquareOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateSquareOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<SquareOptions>
+CreateSquareOptions(flatbuffers::FlatBufferBuilder &_fbb, const SquareOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const SquareOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateSquareOptions(_fbb);
+}
+
+inline ZerosLikeOptionsT *
+ZerosLikeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<ZerosLikeOptionsT>(new ZerosLikeOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void ZerosLikeOptions::UnPackTo(ZerosLikeOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<ZerosLikeOptions>
+ZerosLikeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ZerosLikeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateZerosLikeOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<ZerosLikeOptions>
+CreateZerosLikeOptions(flatbuffers::FlatBufferBuilder &_fbb, const ZerosLikeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const ZerosLikeOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateZerosLikeOptions(_fbb);
+}
+
+inline FillOptionsT *FillOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<FillOptionsT>(new FillOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void FillOptions::UnPackTo(FillOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<FillOptions>
+FillOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const FillOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateFillOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<FillOptions>
+CreateFillOptions(flatbuffers::FlatBufferBuilder &_fbb, const FillOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const FillOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateFillOptions(_fbb);
+}
+
+inline FloorModOptionsT *
+FloorModOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<FloorModOptionsT>(new FloorModOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void FloorModOptions::UnPackTo(FloorModOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<FloorModOptions>
+FloorModOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const FloorModOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateFloorModOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<FloorModOptions>
+CreateFloorModOptions(flatbuffers::FlatBufferBuilder &_fbb, const FloorModOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const FloorModOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateFloorModOptions(_fbb);
+}
+
+inline RangeOptionsT *RangeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<RangeOptionsT>(new RangeOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void RangeOptions::UnPackTo(RangeOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<RangeOptions>
+RangeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const RangeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateRangeOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<RangeOptions>
+CreateRangeOptions(flatbuffers::FlatBufferBuilder &_fbb, const RangeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const RangeOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateRangeOptions(_fbb);
+}
+
+inline LeakyReluOptionsT *
+LeakyReluOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<LeakyReluOptionsT>(new LeakyReluOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void LeakyReluOptions::UnPackTo(LeakyReluOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = alpha();
+ _o->alpha = _e;
+ }
+}
+
+inline flatbuffers::Offset<LeakyReluOptions>
+LeakyReluOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LeakyReluOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateLeakyReluOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<LeakyReluOptions>
+CreateLeakyReluOptions(flatbuffers::FlatBufferBuilder &_fbb, const LeakyReluOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const LeakyReluOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _alpha = _o->alpha;
+ return circle::CreateLeakyReluOptions(_fbb, _alpha);
+}
+
+inline SquaredDifferenceOptionsT *
+SquaredDifferenceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<SquaredDifferenceOptionsT>(new SquaredDifferenceOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void
+SquaredDifferenceOptions::UnPackTo(SquaredDifferenceOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<SquaredDifferenceOptions>
+SquaredDifferenceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+ const SquaredDifferenceOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateSquaredDifferenceOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<SquaredDifferenceOptions>
+CreateSquaredDifferenceOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ const SquaredDifferenceOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const SquaredDifferenceOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateSquaredDifferenceOptions(_fbb);
+}
+
+inline MirrorPadOptionsT *
+MirrorPadOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<MirrorPadOptionsT>(new MirrorPadOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void MirrorPadOptions::UnPackTo(MirrorPadOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = mode();
+ _o->mode = _e;
+ }
+}
+
+inline flatbuffers::Offset<MirrorPadOptions>
+MirrorPadOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MirrorPadOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateMirrorPadOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<MirrorPadOptions>
+CreateMirrorPadOptions(flatbuffers::FlatBufferBuilder &_fbb, const MirrorPadOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const MirrorPadOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _mode = _o->mode;
+ return circle::CreateMirrorPadOptions(_fbb, _mode);
+}
+
+inline UniqueOptionsT *
+UniqueOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<UniqueOptionsT>(new UniqueOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void UniqueOptions::UnPackTo(UniqueOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = idx_out_type();
+ _o->idx_out_type = _e;
+ }
+}
+
+inline flatbuffers::Offset<UniqueOptions>
+UniqueOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const UniqueOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateUniqueOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<UniqueOptions>
+CreateUniqueOptions(flatbuffers::FlatBufferBuilder &_fbb, const UniqueOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const UniqueOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _idx_out_type = _o->idx_out_type;
+ return circle::CreateUniqueOptions(_fbb, _idx_out_type);
+}
+
+inline ReverseV2OptionsT *
+ReverseV2Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<ReverseV2OptionsT>(new ReverseV2OptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void ReverseV2Options::UnPackTo(ReverseV2OptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<ReverseV2Options>
+ReverseV2Options::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ReverseV2OptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateReverseV2Options(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<ReverseV2Options>
+CreateReverseV2Options(flatbuffers::FlatBufferBuilder &_fbb, const ReverseV2OptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const ReverseV2OptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateReverseV2Options(_fbb);
+}
+
+inline AddNOptionsT *AddNOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<AddNOptionsT>(new AddNOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void AddNOptions::UnPackTo(AddNOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<AddNOptions>
+AddNOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const AddNOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateAddNOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<AddNOptions>
+CreateAddNOptions(flatbuffers::FlatBufferBuilder &_fbb, const AddNOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const AddNOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateAddNOptions(_fbb);
+}
+
+inline GatherNdOptionsT *
+GatherNdOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<GatherNdOptionsT>(new GatherNdOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void GatherNdOptions::UnPackTo(GatherNdOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<GatherNdOptions>
+GatherNdOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const GatherNdOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateGatherNdOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<GatherNdOptions>
+CreateGatherNdOptions(flatbuffers::FlatBufferBuilder &_fbb, const GatherNdOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const GatherNdOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateGatherNdOptions(_fbb);
+}
+
+inline WhereOptionsT *WhereOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<WhereOptionsT>(new WhereOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void WhereOptions::UnPackTo(WhereOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<WhereOptions>
+WhereOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const WhereOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateWhereOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<WhereOptions>
+CreateWhereOptions(flatbuffers::FlatBufferBuilder &_fbb, const WhereOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const WhereOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateWhereOptions(_fbb);
+}
+
+inline ReverseSequenceOptionsT *
+ReverseSequenceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<ReverseSequenceOptionsT>(new ReverseSequenceOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void
+ReverseSequenceOptions::UnPackTo(ReverseSequenceOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = seq_dim();
+ _o->seq_dim = _e;
+ }
+ {
+ auto _e = batch_dim();
+ _o->batch_dim = _e;
+ }
+}
+
+inline flatbuffers::Offset<ReverseSequenceOptions>
+ReverseSequenceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+ const ReverseSequenceOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateReverseSequenceOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<ReverseSequenceOptions>
+CreateReverseSequenceOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ const ReverseSequenceOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const ReverseSequenceOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _seq_dim = _o->seq_dim;
+ auto _batch_dim = _o->batch_dim;
+ return circle::CreateReverseSequenceOptions(_fbb, _seq_dim, _batch_dim);
+}
+
+inline MatrixDiagOptionsT *
+MatrixDiagOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<MatrixDiagOptionsT>(new MatrixDiagOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void MatrixDiagOptions::UnPackTo(MatrixDiagOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<MatrixDiagOptions>
+MatrixDiagOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MatrixDiagOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateMatrixDiagOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<MatrixDiagOptions>
+CreateMatrixDiagOptions(flatbuffers::FlatBufferBuilder &_fbb, const MatrixDiagOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const MatrixDiagOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateMatrixDiagOptions(_fbb);
+}
+
+inline QuantizeOptionsT *
+QuantizeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<QuantizeOptionsT>(new QuantizeOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void QuantizeOptions::UnPackTo(QuantizeOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<QuantizeOptions>
+QuantizeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const QuantizeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateQuantizeOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<QuantizeOptions>
+CreateQuantizeOptions(flatbuffers::FlatBufferBuilder &_fbb, const QuantizeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const QuantizeOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateQuantizeOptions(_fbb);
+}
+
+inline MatrixSetDiagOptionsT *
+MatrixSetDiagOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<MatrixSetDiagOptionsT>(new MatrixSetDiagOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void MatrixSetDiagOptions::UnPackTo(MatrixSetDiagOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<MatrixSetDiagOptions>
+MatrixSetDiagOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MatrixSetDiagOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateMatrixSetDiagOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<MatrixSetDiagOptions>
+CreateMatrixSetDiagOptions(flatbuffers::FlatBufferBuilder &_fbb, const MatrixSetDiagOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const MatrixSetDiagOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateMatrixSetDiagOptions(_fbb);
+}
+
+inline IfOptionsT *IfOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<IfOptionsT>(new IfOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void IfOptions::UnPackTo(IfOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = then_subgraph_index();
+ _o->then_subgraph_index = _e;
+ }
+ {
+ auto _e = else_subgraph_index();
+ _o->else_subgraph_index = _e;
+ }
+}
+
+inline flatbuffers::Offset<IfOptions>
+IfOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const IfOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateIfOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<IfOptions>
+CreateIfOptions(flatbuffers::FlatBufferBuilder &_fbb, const IfOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const IfOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _then_subgraph_index = _o->then_subgraph_index;
+ auto _else_subgraph_index = _o->else_subgraph_index;
+ return circle::CreateIfOptions(_fbb, _then_subgraph_index, _else_subgraph_index);
+}
+
+inline CallOnceOptionsT *
+CallOnceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<CallOnceOptionsT>(new CallOnceOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void CallOnceOptions::UnPackTo(CallOnceOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = init_subgraph_index();
+ _o->init_subgraph_index = _e;
+ }
+}
+
+inline flatbuffers::Offset<CallOnceOptions>
+CallOnceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CallOnceOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateCallOnceOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<CallOnceOptions>
+CreateCallOnceOptions(flatbuffers::FlatBufferBuilder &_fbb, const CallOnceOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const CallOnceOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _init_subgraph_index = _o->init_subgraph_index;
+ return circle::CreateCallOnceOptions(_fbb, _init_subgraph_index);
+}
+
+inline WhileOptionsT *WhileOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<WhileOptionsT>(new WhileOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void WhileOptions::UnPackTo(WhileOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = cond_subgraph_index();
+ _o->cond_subgraph_index = _e;
+ }
+ {
+ auto _e = body_subgraph_index();
+ _o->body_subgraph_index = _e;
+ }
+}
+
+inline flatbuffers::Offset<WhileOptions>
+WhileOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const WhileOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateWhileOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<WhileOptions>
+CreateWhileOptions(flatbuffers::FlatBufferBuilder &_fbb, const WhileOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const WhileOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _cond_subgraph_index = _o->cond_subgraph_index;
+ auto _body_subgraph_index = _o->body_subgraph_index;
+ return circle::CreateWhileOptions(_fbb, _cond_subgraph_index, _body_subgraph_index);
+}
+
+inline NonMaxSuppressionV4OptionsT *
+NonMaxSuppressionV4Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<NonMaxSuppressionV4OptionsT>(new NonMaxSuppressionV4OptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void
+NonMaxSuppressionV4Options::UnPackTo(NonMaxSuppressionV4OptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<NonMaxSuppressionV4Options>
+NonMaxSuppressionV4Options::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+ const NonMaxSuppressionV4OptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateNonMaxSuppressionV4Options(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<NonMaxSuppressionV4Options>
+CreateNonMaxSuppressionV4Options(flatbuffers::FlatBufferBuilder &_fbb,
+ const NonMaxSuppressionV4OptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const NonMaxSuppressionV4OptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateNonMaxSuppressionV4Options(_fbb);
+}
+
+inline NonMaxSuppressionV5OptionsT *
+NonMaxSuppressionV5Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<NonMaxSuppressionV5OptionsT>(new NonMaxSuppressionV5OptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void
+NonMaxSuppressionV5Options::UnPackTo(NonMaxSuppressionV5OptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<NonMaxSuppressionV5Options>
+NonMaxSuppressionV5Options::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+ const NonMaxSuppressionV5OptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateNonMaxSuppressionV5Options(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<NonMaxSuppressionV5Options>
+CreateNonMaxSuppressionV5Options(flatbuffers::FlatBufferBuilder &_fbb,
+ const NonMaxSuppressionV5OptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const NonMaxSuppressionV5OptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateNonMaxSuppressionV5Options(_fbb);
+}
+
+inline ScatterNdOptionsT *
+ScatterNdOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<ScatterNdOptionsT>(new ScatterNdOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void ScatterNdOptions::UnPackTo(ScatterNdOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<ScatterNdOptions>
+ScatterNdOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ScatterNdOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateScatterNdOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<ScatterNdOptions>
+CreateScatterNdOptions(flatbuffers::FlatBufferBuilder &_fbb, const ScatterNdOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const ScatterNdOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateScatterNdOptions(_fbb);
+}
+
+inline SelectV2OptionsT *
+SelectV2Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<SelectV2OptionsT>(new SelectV2OptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void SelectV2Options::UnPackTo(SelectV2OptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<SelectV2Options>
+SelectV2Options::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SelectV2OptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateSelectV2Options(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<SelectV2Options>
+CreateSelectV2Options(flatbuffers::FlatBufferBuilder &_fbb, const SelectV2OptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const SelectV2OptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateSelectV2Options(_fbb);
+}
+
+inline DensifyOptionsT *
+DensifyOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<DensifyOptionsT>(new DensifyOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void DensifyOptions::UnPackTo(DensifyOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<DensifyOptions>
+DensifyOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const DensifyOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateDensifyOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<DensifyOptions>
+CreateDensifyOptions(flatbuffers::FlatBufferBuilder &_fbb, const DensifyOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const DensifyOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateDensifyOptions(_fbb);
+}
+
+inline SegmentSumOptionsT *
+SegmentSumOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<SegmentSumOptionsT>(new SegmentSumOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void SegmentSumOptions::UnPackTo(SegmentSumOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<SegmentSumOptions>
+SegmentSumOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SegmentSumOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateSegmentSumOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<SegmentSumOptions>
+CreateSegmentSumOptions(flatbuffers::FlatBufferBuilder &_fbb, const SegmentSumOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const SegmentSumOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateSegmentSumOptions(_fbb);
+}
+
+inline BatchMatMulOptionsT *
+BatchMatMulOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<BatchMatMulOptionsT>(new BatchMatMulOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void BatchMatMulOptions::UnPackTo(BatchMatMulOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = adjoint_lhs();
+ _o->adjoint_lhs = _e;
+ }
+ {
+ auto _e = adjoint_rhs();
+ _o->adjoint_rhs = _e;
+ }
+ {
+ auto _e = asymmetric_quantize_inputs();
+ _o->asymmetric_quantize_inputs = _e;
+ }
+}
+
+inline flatbuffers::Offset<BatchMatMulOptions>
+BatchMatMulOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const BatchMatMulOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateBatchMatMulOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<BatchMatMulOptions>
+CreateBatchMatMulOptions(flatbuffers::FlatBufferBuilder &_fbb, const BatchMatMulOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const BatchMatMulOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _adjoint_lhs = _o->adjoint_lhs;
+ auto _adjoint_rhs = _o->adjoint_rhs;
+ auto _asymmetric_quantize_inputs = _o->asymmetric_quantize_inputs;
+ return circle::CreateBatchMatMulOptions(_fbb, _adjoint_lhs, _adjoint_rhs,
+ _asymmetric_quantize_inputs);
+}
+
+inline CumsumOptionsT *
+CumsumOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<CumsumOptionsT>(new CumsumOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void CumsumOptions::UnPackTo(CumsumOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = exclusive();
+ _o->exclusive = _e;
+ }
+ {
+ auto _e = reverse();
+ _o->reverse = _e;
+ }
+}
+
+inline flatbuffers::Offset<CumsumOptions>
+CumsumOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CumsumOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateCumsumOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<CumsumOptions>
+CreateCumsumOptions(flatbuffers::FlatBufferBuilder &_fbb, const CumsumOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const CumsumOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _exclusive = _o->exclusive;
+ auto _reverse = _o->reverse;
+ return circle::CreateCumsumOptions(_fbb, _exclusive, _reverse);
+}
+
+inline BroadcastToOptionsT *
+BroadcastToOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<BroadcastToOptionsT>(new BroadcastToOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void BroadcastToOptions::UnPackTo(BroadcastToOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<BroadcastToOptions>
+BroadcastToOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const BroadcastToOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateBroadcastToOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<BroadcastToOptions>
+CreateBroadcastToOptions(flatbuffers::FlatBufferBuilder &_fbb, const BroadcastToOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const BroadcastToOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateBroadcastToOptions(_fbb);
+}
+
+inline Rfft2dOptionsT *
+Rfft2dOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<Rfft2dOptionsT>(new Rfft2dOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void Rfft2dOptions::UnPackTo(Rfft2dOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<Rfft2dOptions>
+Rfft2dOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const Rfft2dOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateRfft2dOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<Rfft2dOptions>
+CreateRfft2dOptions(flatbuffers::FlatBufferBuilder &_fbb, const Rfft2dOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const Rfft2dOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateRfft2dOptions(_fbb);
+}
+
+inline HashtableOptionsT *
+HashtableOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<HashtableOptionsT>(new HashtableOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void HashtableOptions::UnPackTo(HashtableOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = table_id();
+ _o->table_id = _e;
+ }
+ {
+ auto _e = key_dtype();
+ _o->key_dtype = _e;
+ }
+ {
+ auto _e = value_dtype();
+ _o->value_dtype = _e;
+ }
+}
+
+inline flatbuffers::Offset<HashtableOptions>
+HashtableOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const HashtableOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateHashtableOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<HashtableOptions>
+CreateHashtableOptions(flatbuffers::FlatBufferBuilder &_fbb, const HashtableOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const HashtableOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _table_id = _o->table_id;
+ auto _key_dtype = _o->key_dtype;
+ auto _value_dtype = _o->value_dtype;
+ return circle::CreateHashtableOptions(_fbb, _table_id, _key_dtype, _value_dtype);
+}
+
+inline HashtableFindOptionsT *
+HashtableFindOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<HashtableFindOptionsT>(new HashtableFindOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void HashtableFindOptions::UnPackTo(HashtableFindOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<HashtableFindOptions>
+HashtableFindOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const HashtableFindOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateHashtableFindOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<HashtableFindOptions>
+CreateHashtableFindOptions(flatbuffers::FlatBufferBuilder &_fbb, const HashtableFindOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const HashtableFindOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateHashtableFindOptions(_fbb);
+}
+
+inline HashtableImportOptionsT *
+HashtableImportOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<HashtableImportOptionsT>(new HashtableImportOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void
+HashtableImportOptions::UnPackTo(HashtableImportOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<HashtableImportOptions>
+HashtableImportOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+ const HashtableImportOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateHashtableImportOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<HashtableImportOptions>
+CreateHashtableImportOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ const HashtableImportOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const HashtableImportOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateHashtableImportOptions(_fbb);
+}
+
+inline HashtableSizeOptionsT *
+HashtableSizeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<HashtableSizeOptionsT>(new HashtableSizeOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void HashtableSizeOptions::UnPackTo(HashtableSizeOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<HashtableSizeOptions>
+HashtableSizeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const HashtableSizeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateHashtableSizeOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<HashtableSizeOptions>
+CreateHashtableSizeOptions(flatbuffers::FlatBufferBuilder &_fbb, const HashtableSizeOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const HashtableSizeOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateHashtableSizeOptions(_fbb);
+}
+
+inline VarHandleOptionsT *
+VarHandleOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<VarHandleOptionsT>(new VarHandleOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void VarHandleOptions::UnPackTo(VarHandleOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = container();
+ if (_e)
+ _o->container = _e->str();
+ }
+ {
+ auto _e = shared_name();
+ if (_e)
+ _o->shared_name = _e->str();
+ }
+}
+
+inline flatbuffers::Offset<VarHandleOptions>
+VarHandleOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const VarHandleOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateVarHandleOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<VarHandleOptions>
+CreateVarHandleOptions(flatbuffers::FlatBufferBuilder &_fbb, const VarHandleOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const VarHandleOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _container = _o->container.empty() ? 0 : _fbb.CreateString(_o->container);
+ auto _shared_name = _o->shared_name.empty() ? 0 : _fbb.CreateString(_o->shared_name);
+ return circle::CreateVarHandleOptions(_fbb, _container, _shared_name);
+}
+
+inline ReadVariableOptionsT *
+ReadVariableOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<ReadVariableOptionsT>(new ReadVariableOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void ReadVariableOptions::UnPackTo(ReadVariableOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<ReadVariableOptions>
+ReadVariableOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ReadVariableOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateReadVariableOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<ReadVariableOptions>
+CreateReadVariableOptions(flatbuffers::FlatBufferBuilder &_fbb, const ReadVariableOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const ReadVariableOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateReadVariableOptions(_fbb);
+}
+
+inline AssignVariableOptionsT *
+AssignVariableOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<AssignVariableOptionsT>(new AssignVariableOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void AssignVariableOptions::UnPackTo(AssignVariableOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+}
+
+inline flatbuffers::Offset<AssignVariableOptions>
+AssignVariableOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const AssignVariableOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateAssignVariableOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<AssignVariableOptions>
+CreateAssignVariableOptions(flatbuffers::FlatBufferBuilder &_fbb, const AssignVariableOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const AssignVariableOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ return circle::CreateAssignVariableOptions(_fbb);
+}
+
+inline RandomOptionsT *
+RandomOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<RandomOptionsT>(new RandomOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void RandomOptions::UnPackTo(RandomOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = seed();
+ _o->seed = _e;
+ }
+ {
+ auto _e = seed2();
+ _o->seed2 = _e;
+ }
+}
+
+inline flatbuffers::Offset<RandomOptions>
+RandomOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const RandomOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateRandomOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<RandomOptions>
+CreateRandomOptions(flatbuffers::FlatBufferBuilder &_fbb, const RandomOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const RandomOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _seed = _o->seed;
+ auto _seed2 = _o->seed2;
+ return circle::CreateRandomOptions(_fbb, _seed, _seed2);
+}
+
+inline BCQGatherOptionsT *
+BCQGatherOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<BCQGatherOptionsT>(new BCQGatherOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void BCQGatherOptions::UnPackTo(BCQGatherOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = input_hidden_size();
+ _o->input_hidden_size = _e;
+ }
+ {
+ auto _e = axis();
+ _o->axis = _e;
+ }
+}
+
+inline flatbuffers::Offset<BCQGatherOptions>
+BCQGatherOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const BCQGatherOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateBCQGatherOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<BCQGatherOptions>
+CreateBCQGatherOptions(flatbuffers::FlatBufferBuilder &_fbb, const BCQGatherOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const BCQGatherOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _input_hidden_size = _o->input_hidden_size;
+ auto _axis = _o->axis;
+ return circle::CreateBCQGatherOptions(_fbb, _input_hidden_size, _axis);
+}
+
+inline BCQFullyConnectedOptionsT *
+BCQFullyConnectedOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<BCQFullyConnectedOptionsT>(new BCQFullyConnectedOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void
+BCQFullyConnectedOptions::UnPackTo(BCQFullyConnectedOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = weights_hidden_size();
+ _o->weights_hidden_size = _e;
+ }
+ {
+ auto _e = fused_activation_function();
+ _o->fused_activation_function = _e;
+ }
+}
+
+inline flatbuffers::Offset<BCQFullyConnectedOptions>
+BCQFullyConnectedOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+ const BCQFullyConnectedOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateBCQFullyConnectedOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<BCQFullyConnectedOptions>
+CreateBCQFullyConnectedOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ const BCQFullyConnectedOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const BCQFullyConnectedOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _weights_hidden_size = _o->weights_hidden_size;
+ auto _fused_activation_function = _o->fused_activation_function;
+ return circle::CreateBCQFullyConnectedOptions(_fbb, _weights_hidden_size,
+ _fused_activation_function);
+}
+
+inline InstanceNormOptionsT *
+InstanceNormOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<InstanceNormOptionsT>(new InstanceNormOptionsT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void InstanceNormOptions::UnPackTo(InstanceNormOptionsT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = epsilon();
+ _o->epsilon = _e;
+ }
+ {
+ auto _e = fused_activation_function();
+ _o->fused_activation_function = _e;
+ }
+}
+
+inline flatbuffers::Offset<InstanceNormOptions>
+InstanceNormOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const InstanceNormOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateInstanceNormOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<InstanceNormOptions>
+CreateInstanceNormOptions(flatbuffers::FlatBufferBuilder &_fbb, const InstanceNormOptionsT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const InstanceNormOptionsT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _epsilon = _o->epsilon;
+ auto _fused_activation_function = _o->fused_activation_function;
+ return circle::CreateInstanceNormOptions(_fbb, _epsilon, _fused_activation_function);
+}
+
+inline OperatorCodeT *OperatorCode::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<OperatorCodeT>(new OperatorCodeT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void OperatorCode::UnPackTo(OperatorCodeT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = deprecated_builtin_code();
+ _o->deprecated_builtin_code = _e;
+ }
+ {
+ auto _e = custom_code();
+ if (_e)
+ _o->custom_code = _e->str();
+ }
+ {
+ auto _e = version();
+ _o->version = _e;
+ }
+ {
+ auto _e = builtin_code();
+ _o->builtin_code = _e;
+ }
+}
+
+inline flatbuffers::Offset<OperatorCode>
+OperatorCode::Pack(flatbuffers::FlatBufferBuilder &_fbb, const OperatorCodeT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateOperatorCode(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<OperatorCode>
+CreateOperatorCode(flatbuffers::FlatBufferBuilder &_fbb, const OperatorCodeT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const OperatorCodeT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _deprecated_builtin_code = _o->deprecated_builtin_code;
+ auto _custom_code = _o->custom_code.empty() ? 0 : _fbb.CreateString(_o->custom_code);
+ auto _version = _o->version;
+ auto _builtin_code = _o->builtin_code;
+ return circle::CreateOperatorCode(_fbb, _deprecated_builtin_code, _custom_code, _version,
+ _builtin_code);
+}
+
+inline OperatorT *Operator::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<OperatorT>(new OperatorT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void Operator::UnPackTo(OperatorT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = opcode_index();
+ _o->opcode_index = _e;
+ }
+ {
+ auto _e = inputs();
+ if (_e)
+ {
+ _o->inputs.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->inputs[_i] = _e->Get(_i);
+ }
+ }
+ }
+ {
+ auto _e = outputs();
+ if (_e)
+ {
+ _o->outputs.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->outputs[_i] = _e->Get(_i);
+ }
+ }
+ }
+ {
+ auto _e = builtin_options_type();
+ _o->builtin_options.type = _e;
+ }
+ {
+ auto _e = builtin_options();
+ if (_e)
+ _o->builtin_options.value =
+ circle::BuiltinOptionsUnion::UnPack(_e, builtin_options_type(), _resolver);
+ }
+ {
+ auto _e = custom_options();
+ if (_e)
+ {
+ _o->custom_options.resize(_e->size());
+ std::copy(_e->begin(), _e->end(), _o->custom_options.begin());
+ }
+ }
+ {
+ auto _e = custom_options_format();
+ _o->custom_options_format = _e;
+ }
+ {
+ auto _e = mutating_variable_inputs();
+ if (_e)
+ {
+ _o->mutating_variable_inputs.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->mutating_variable_inputs[_i] = _e->Get(_i) != 0;
+ }
+ }
+ }
+ {
+ auto _e = intermediates();
+ if (_e)
+ {
+ _o->intermediates.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->intermediates[_i] = _e->Get(_i);
+ }
+ }
+ }
+}
+
+inline flatbuffers::Offset<Operator>
+Operator::Pack(flatbuffers::FlatBufferBuilder &_fbb, const OperatorT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateOperator(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<Operator>
+CreateOperator(flatbuffers::FlatBufferBuilder &_fbb, const OperatorT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const OperatorT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _opcode_index = _o->opcode_index;
+ auto _inputs = _o->inputs.size() ? _fbb.CreateVector(_o->inputs) : 0;
+ auto _outputs = _o->outputs.size() ? _fbb.CreateVector(_o->outputs) : 0;
+ auto _builtin_options_type = _o->builtin_options.type;
+ auto _builtin_options = _o->builtin_options.Pack(_fbb);
+ auto _custom_options = _o->custom_options.size() ? _fbb.CreateVector(_o->custom_options) : 0;
+ auto _custom_options_format = _o->custom_options_format;
+ auto _mutating_variable_inputs =
+ _o->mutating_variable_inputs.size() ? _fbb.CreateVector(_o->mutating_variable_inputs) : 0;
+ auto _intermediates = _o->intermediates.size() ? _fbb.CreateVector(_o->intermediates) : 0;
+ return circle::CreateOperator(_fbb, _opcode_index, _inputs, _outputs, _builtin_options_type,
+ _builtin_options, _custom_options, _custom_options_format,
+ _mutating_variable_inputs, _intermediates);
+}
+
+inline SubGraphT *SubGraph::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<SubGraphT>(new SubGraphT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void SubGraph::UnPackTo(SubGraphT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = tensors();
+ if (_e)
+ {
+ _o->tensors.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->tensors[_i] = std::unique_ptr<circle::TensorT>(_e->Get(_i)->UnPack(_resolver));
+ }
+ }
+ }
+ {
+ auto _e = inputs();
+ if (_e)
+ {
+ _o->inputs.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->inputs[_i] = _e->Get(_i);
+ }
+ }
+ }
+ {
+ auto _e = outputs();
+ if (_e)
+ {
+ _o->outputs.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->outputs[_i] = _e->Get(_i);
+ }
+ }
+ }
+ {
+ auto _e = operators();
+ if (_e)
+ {
+ _o->operators.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->operators[_i] = std::unique_ptr<circle::OperatorT>(_e->Get(_i)->UnPack(_resolver));
+ }
+ }
+ }
+ {
+ auto _e = name();
+ if (_e)
+ _o->name = _e->str();
+ }
+ {
+ auto _e = data_format();
+ _o->data_format = _e;
+ }
+}
+
+inline flatbuffers::Offset<SubGraph>
+SubGraph::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SubGraphT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateSubGraph(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<SubGraph>
+CreateSubGraph(flatbuffers::FlatBufferBuilder &_fbb, const SubGraphT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const SubGraphT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _tensors =
+ _o->tensors.size()
+ ? _fbb.CreateVector<flatbuffers::Offset<circle::Tensor>>(
+ _o->tensors.size(),
+ [](size_t i, _VectorArgs *__va) {
+ return CreateTensor(*__va->__fbb, __va->__o->tensors[i].get(), __va->__rehasher);
+ },
+ &_va)
+ : 0;
+ auto _inputs = _o->inputs.size() ? _fbb.CreateVector(_o->inputs) : 0;
+ auto _outputs = _o->outputs.size() ? _fbb.CreateVector(_o->outputs) : 0;
+ auto _operators =
+ _o->operators.size()
+ ? _fbb.CreateVector<flatbuffers::Offset<circle::Operator>>(
+ _o->operators.size(),
+ [](size_t i, _VectorArgs *__va) {
+ return CreateOperator(*__va->__fbb, __va->__o->operators[i].get(), __va->__rehasher);
+ },
+ &_va)
+ : 0;
+ auto _name = _o->name.empty() ? 0 : _fbb.CreateString(_o->name);
+ auto _data_format = _o->data_format;
+ return circle::CreateSubGraph(_fbb, _tensors, _inputs, _outputs, _operators, _name, _data_format);
+}
+
+inline BufferT *Buffer::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<BufferT>(new BufferT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void Buffer::UnPackTo(BufferT *_o, const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = data();
+ if (_e)
+ {
+ _o->data.resize(_e->size());
+ std::copy(_e->begin(), _e->end(), _o->data.begin());
+ }
+ }
+}
+
+inline flatbuffers::Offset<Buffer> Buffer::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+ const BufferT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateBuffer(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<Buffer> CreateBuffer(flatbuffers::FlatBufferBuilder &_fbb,
+ const BufferT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const BufferT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ _fbb.ForceVectorAlignment(_o->data.size(), sizeof(uint8_t), 16);
+ auto _data = _o->data.size() ? _fbb.CreateVector(_o->data) : 0;
+ return circle::CreateBuffer(_fbb, _data);
+}
+
+inline MetadataT *Metadata::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<MetadataT>(new MetadataT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void Metadata::UnPackTo(MetadataT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = name();
+ if (_e)
+ _o->name = _e->str();
+ }
+ {
+ auto _e = buffer();
+ _o->buffer = _e;
+ }
+}
+
+inline flatbuffers::Offset<Metadata>
+Metadata::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MetadataT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateMetadata(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<Metadata>
+CreateMetadata(flatbuffers::FlatBufferBuilder &_fbb, const MetadataT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const MetadataT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _name = _o->name.empty() ? 0 : _fbb.CreateString(_o->name);
+ auto _buffer = _o->buffer;
+ return circle::CreateMetadata(_fbb, _name, _buffer);
+}
+
+inline TensorMapT *TensorMap::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<TensorMapT>(new TensorMapT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void TensorMap::UnPackTo(TensorMapT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = name();
+ if (_e)
+ _o->name = _e->str();
+ }
+ {
+ auto _e = tensor_index();
+ _o->tensor_index = _e;
+ }
+}
+
+inline flatbuffers::Offset<TensorMap>
+TensorMap::Pack(flatbuffers::FlatBufferBuilder &_fbb, const TensorMapT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateTensorMap(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<TensorMap>
+CreateTensorMap(flatbuffers::FlatBufferBuilder &_fbb, const TensorMapT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const TensorMapT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _name = _o->name.empty() ? 0 : _fbb.CreateString(_o->name);
+ auto _tensor_index = _o->tensor_index;
+ return circle::CreateTensorMap(_fbb, _name, _tensor_index);
+}
+
+inline SignatureDefT *SignatureDef::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<SignatureDefT>(new SignatureDefT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void SignatureDef::UnPackTo(SignatureDefT *_o,
+ const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = inputs();
+ if (_e)
+ {
+ _o->inputs.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->inputs[_i] = std::unique_ptr<circle::TensorMapT>(_e->Get(_i)->UnPack(_resolver));
+ }
+ }
+ }
+ {
+ auto _e = outputs();
+ if (_e)
+ {
+ _o->outputs.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->outputs[_i] = std::unique_ptr<circle::TensorMapT>(_e->Get(_i)->UnPack(_resolver));
+ }
+ }
+ }
+ {
+ auto _e = signature_key();
+ if (_e)
+ _o->signature_key = _e->str();
+ }
+ {
+ auto _e = subgraph_index();
+ _o->subgraph_index = _e;
+ }
+}
+
+inline flatbuffers::Offset<SignatureDef>
+SignatureDef::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SignatureDefT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateSignatureDef(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<SignatureDef>
+CreateSignatureDef(flatbuffers::FlatBufferBuilder &_fbb, const SignatureDefT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const SignatureDefT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _inputs =
+ _o->inputs.size()
+ ? _fbb.CreateVector<flatbuffers::Offset<circle::TensorMap>>(
+ _o->inputs.size(),
+ [](size_t i, _VectorArgs *__va) {
+ return CreateTensorMap(*__va->__fbb, __va->__o->inputs[i].get(), __va->__rehasher);
+ },
+ &_va)
+ : 0;
+ auto _outputs =
+ _o->outputs.size()
+ ? _fbb.CreateVector<flatbuffers::Offset<circle::TensorMap>>(
+ _o->outputs.size(),
+ [](size_t i, _VectorArgs *__va) {
+ return CreateTensorMap(*__va->__fbb, __va->__o->outputs[i].get(), __va->__rehasher);
+ },
+ &_va)
+ : 0;
+ auto _signature_key = _o->signature_key.empty() ? 0 : _fbb.CreateString(_o->signature_key);
+ auto _subgraph_index = _o->subgraph_index;
+ return circle::CreateSignatureDef(_fbb, _inputs, _outputs, _signature_key, _subgraph_index);
+}
+
+inline ModelT *Model::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+ auto _o = std::unique_ptr<ModelT>(new ModelT());
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void Model::UnPackTo(ModelT *_o, const flatbuffers::resolver_function_t *_resolver) const
+{
+ (void)_o;
+ (void)_resolver;
+ {
+ auto _e = version();
+ _o->version = _e;
+ }
+ {
+ auto _e = operator_codes();
+ if (_e)
+ {
+ _o->operator_codes.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->operator_codes[_i] =
+ std::unique_ptr<circle::OperatorCodeT>(_e->Get(_i)->UnPack(_resolver));
+ }
+ }
+ }
+ {
+ auto _e = subgraphs();
+ if (_e)
+ {
+ _o->subgraphs.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->subgraphs[_i] = std::unique_ptr<circle::SubGraphT>(_e->Get(_i)->UnPack(_resolver));
+ }
+ }
+ }
+ {
+ auto _e = description();
+ if (_e)
+ _o->description = _e->str();
+ }
+ {
+ auto _e = buffers();
+ if (_e)
+ {
+ _o->buffers.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->buffers[_i] = std::unique_ptr<circle::BufferT>(_e->Get(_i)->UnPack(_resolver));
+ }
+ }
+ }
+ {
+ auto _e = metadata_buffer();
+ if (_e)
+ {
+ _o->metadata_buffer.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->metadata_buffer[_i] = _e->Get(_i);
+ }
+ }
+ }
+ {
+ auto _e = metadata();
+ if (_e)
+ {
+ _o->metadata.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->metadata[_i] = std::unique_ptr<circle::MetadataT>(_e->Get(_i)->UnPack(_resolver));
+ }
+ }
+ }
+ {
+ auto _e = signature_defs();
+ if (_e)
+ {
+ _o->signature_defs.resize(_e->size());
+ for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+ {
+ _o->signature_defs[_i] =
+ std::unique_ptr<circle::SignatureDefT>(_e->Get(_i)->UnPack(_resolver));
+ }
+ }
+ }
+}
+
+inline flatbuffers::Offset<Model> Model::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+ const ModelT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ return CreateModel(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<Model> CreateModel(flatbuffers::FlatBufferBuilder &_fbb,
+ const ModelT *_o,
+ const flatbuffers::rehasher_function_t *_rehasher)
+{
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs
+ {
+ flatbuffers::FlatBufferBuilder *__fbb;
+ const ModelT *__o;
+ const flatbuffers::rehasher_function_t *__rehasher;
+ } _va = {&_fbb, _o, _rehasher};
+ (void)_va;
+ auto _version = _o->version;
+ auto _operator_codes =
+ _o->operator_codes.size()
+ ? _fbb.CreateVector<flatbuffers::Offset<circle::OperatorCode>>(
+ _o->operator_codes.size(),
+ [](size_t i, _VectorArgs *__va) {
+ return CreateOperatorCode(*__va->__fbb, __va->__o->operator_codes[i].get(),
+ __va->__rehasher);
+ },
+ &_va)
+ : 0;
+ auto _subgraphs =
+ _o->subgraphs.size()
+ ? _fbb.CreateVector<flatbuffers::Offset<circle::SubGraph>>(
+ _o->subgraphs.size(),
+ [](size_t i, _VectorArgs *__va) {
+ return CreateSubGraph(*__va->__fbb, __va->__o->subgraphs[i].get(), __va->__rehasher);
+ },
+ &_va)
+ : 0;
+ auto _description = _o->description.empty() ? 0 : _fbb.CreateString(_o->description);
+ auto _buffers =
+ _o->buffers.size()
+ ? _fbb.CreateVector<flatbuffers::Offset<circle::Buffer>>(
+ _o->buffers.size(),
+ [](size_t i, _VectorArgs *__va) {
+ return CreateBuffer(*__va->__fbb, __va->__o->buffers[i].get(), __va->__rehasher);
+ },
+ &_va)
+ : 0;
+ auto _metadata_buffer = _o->metadata_buffer.size() ? _fbb.CreateVector(_o->metadata_buffer) : 0;
+ auto _metadata =
+ _o->metadata.size()
+ ? _fbb.CreateVector<flatbuffers::Offset<circle::Metadata>>(
+ _o->metadata.size(),
+ [](size_t i, _VectorArgs *__va) {
+ return CreateMetadata(*__va->__fbb, __va->__o->metadata[i].get(), __va->__rehasher);
+ },
+ &_va)
+ : 0;
+ auto _signature_defs =
+ _o->signature_defs.size()
+ ? _fbb.CreateVector<flatbuffers::Offset<circle::SignatureDef>>(
+ _o->signature_defs.size(),
+ [](size_t i, _VectorArgs *__va) {
+ return CreateSignatureDef(*__va->__fbb, __va->__o->signature_defs[i].get(),
+ __va->__rehasher);
+ },
+ &_va)
+ : 0;
+ return circle::CreateModel(_fbb, _version, _operator_codes, _subgraphs, _description, _buffers,
+ _metadata_buffer, _metadata, _signature_defs);
+}
+
+inline bool VerifyQuantizationDetails(flatbuffers::Verifier &verifier, const void *obj,
+ QuantizationDetails type)
+{
+ switch (type)
+ {
+ case QuantizationDetails_NONE:
+ {
+ return true;
+ }
+ case QuantizationDetails_CustomQuantization:
+ {
+ auto ptr = reinterpret_cast<const circle::CustomQuantization *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ default:
+ return true;
+ }
+}
+
+inline bool
+VerifyQuantizationDetailsVector(flatbuffers::Verifier &verifier,
+ const flatbuffers::Vector<flatbuffers::Offset<void>> *values,
+ const flatbuffers::Vector<uint8_t> *types)
+{
+ if (!values || !types)
+ return !values && !types;
+ if (values->size() != types->size())
+ return false;
+ for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i)
+ {
+ if (!VerifyQuantizationDetails(verifier, values->Get(i),
+ types->GetEnum<QuantizationDetails>(i)))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+inline void *QuantizationDetailsUnion::UnPack(const void *obj, QuantizationDetails type,
+ const flatbuffers::resolver_function_t *resolver)
+{
+ switch (type)
+ {
+ case QuantizationDetails_CustomQuantization:
+ {
+ auto ptr = reinterpret_cast<const circle::CustomQuantization *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ default:
+ return nullptr;
+ }
+}
+
+inline flatbuffers::Offset<void>
+QuantizationDetailsUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+ const flatbuffers::rehasher_function_t *_rehasher) const
+{
+ switch (type)
+ {
+ case QuantizationDetails_CustomQuantization:
+ {
+ auto ptr = reinterpret_cast<const circle::CustomQuantizationT *>(value);
+ return CreateCustomQuantization(_fbb, ptr, _rehasher).Union();
+ }
+ default:
+ return 0;
+ }
+}
+
+inline QuantizationDetailsUnion::QuantizationDetailsUnion(const QuantizationDetailsUnion &u)
+ : type(u.type), value(nullptr)
+{
+ switch (type)
+ {
+ case QuantizationDetails_CustomQuantization:
+ {
+ value =
+ new circle::CustomQuantizationT(*reinterpret_cast<circle::CustomQuantizationT *>(u.value));
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+inline void QuantizationDetailsUnion::Reset()
+{
+ switch (type)
+ {
+ case QuantizationDetails_CustomQuantization:
+ {
+ auto ptr = reinterpret_cast<circle::CustomQuantizationT *>(value);
+ delete ptr;
+ break;
+ }
+ default:
+ break;
+ }
+ value = nullptr;
+ type = QuantizationDetails_NONE;
+}
+
+inline bool VerifySparseIndexVector(flatbuffers::Verifier &verifier, const void *obj,
+ SparseIndexVector type)
+{
+ switch (type)
+ {
+ case SparseIndexVector_NONE:
+ {
+ return true;
+ }
+ case SparseIndexVector_Int32Vector:
+ {
+ auto ptr = reinterpret_cast<const circle::Int32Vector *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case SparseIndexVector_Uint16Vector:
+ {
+ auto ptr = reinterpret_cast<const circle::Uint16Vector *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case SparseIndexVector_Uint8Vector:
+ {
+ auto ptr = reinterpret_cast<const circle::Uint8Vector *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ default:
+ return true;
+ }
+}
+
+inline bool
+VerifySparseIndexVectorVector(flatbuffers::Verifier &verifier,
+ const flatbuffers::Vector<flatbuffers::Offset<void>> *values,
+ const flatbuffers::Vector<uint8_t> *types)
+{
+ if (!values || !types)
+ return !values && !types;
+ if (values->size() != types->size())
+ return false;
+ for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i)
+ {
+ if (!VerifySparseIndexVector(verifier, values->Get(i), types->GetEnum<SparseIndexVector>(i)))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+inline void *SparseIndexVectorUnion::UnPack(const void *obj, SparseIndexVector type,
+ const flatbuffers::resolver_function_t *resolver)
+{
+ switch (type)
+ {
+ case SparseIndexVector_Int32Vector:
+ {
+ auto ptr = reinterpret_cast<const circle::Int32Vector *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case SparseIndexVector_Uint16Vector:
+ {
+ auto ptr = reinterpret_cast<const circle::Uint16Vector *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case SparseIndexVector_Uint8Vector:
+ {
+ auto ptr = reinterpret_cast<const circle::Uint8Vector *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ default:
+ return nullptr;
+ }
+}
+
+inline flatbuffers::Offset<void>
+SparseIndexVectorUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+ const flatbuffers::rehasher_function_t *_rehasher) const
+{
+ switch (type)
+ {
+ case SparseIndexVector_Int32Vector:
+ {
+ auto ptr = reinterpret_cast<const circle::Int32VectorT *>(value);
+ return CreateInt32Vector(_fbb, ptr, _rehasher).Union();
+ }
+ case SparseIndexVector_Uint16Vector:
+ {
+ auto ptr = reinterpret_cast<const circle::Uint16VectorT *>(value);
+ return CreateUint16Vector(_fbb, ptr, _rehasher).Union();
+ }
+ case SparseIndexVector_Uint8Vector:
+ {
+ auto ptr = reinterpret_cast<const circle::Uint8VectorT *>(value);
+ return CreateUint8Vector(_fbb, ptr, _rehasher).Union();
+ }
+ default:
+ return 0;
+ }
+}
+
+inline SparseIndexVectorUnion::SparseIndexVectorUnion(const SparseIndexVectorUnion &u)
+ : type(u.type), value(nullptr)
+{
+ switch (type)
+ {
+ case SparseIndexVector_Int32Vector:
+ {
+ value = new circle::Int32VectorT(*reinterpret_cast<circle::Int32VectorT *>(u.value));
+ break;
+ }
+ case SparseIndexVector_Uint16Vector:
+ {
+ value = new circle::Uint16VectorT(*reinterpret_cast<circle::Uint16VectorT *>(u.value));
+ break;
+ }
+ case SparseIndexVector_Uint8Vector:
+ {
+ value = new circle::Uint8VectorT(*reinterpret_cast<circle::Uint8VectorT *>(u.value));
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+inline void SparseIndexVectorUnion::Reset()
+{
+ switch (type)
+ {
+ case SparseIndexVector_Int32Vector:
+ {
+ auto ptr = reinterpret_cast<circle::Int32VectorT *>(value);
+ delete ptr;
+ break;
+ }
+ case SparseIndexVector_Uint16Vector:
+ {
+ auto ptr = reinterpret_cast<circle::Uint16VectorT *>(value);
+ delete ptr;
+ break;
+ }
+ case SparseIndexVector_Uint8Vector:
+ {
+ auto ptr = reinterpret_cast<circle::Uint8VectorT *>(value);
+ delete ptr;
+ break;
+ }
+ default:
+ break;
+ }
+ value = nullptr;
+ type = SparseIndexVector_NONE;
+}
+
+inline bool VerifyBuiltinOptions(flatbuffers::Verifier &verifier, const void *obj,
+ BuiltinOptions type)
+{
+ switch (type)
+ {
+ case BuiltinOptions_NONE:
+ {
+ return true;
+ }
+ case BuiltinOptions_Conv2DOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::Conv2DOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_DepthwiseConv2DOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::DepthwiseConv2DOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_ConcatEmbeddingsOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ConcatEmbeddingsOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_LSHProjectionOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LSHProjectionOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_Pool2DOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::Pool2DOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_SVDFOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SVDFOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_RNNOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::RNNOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_FullyConnectedOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::FullyConnectedOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_SoftmaxOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SoftmaxOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_ConcatenationOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ConcatenationOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_AddOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::AddOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_L2NormOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::L2NormOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_LocalResponseNormalizationOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LocalResponseNormalizationOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_LSTMOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LSTMOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_ResizeBilinearOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ResizeBilinearOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_CallOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::CallOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_ReshapeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ReshapeOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_SkipGramOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SkipGramOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_SpaceToDepthOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SpaceToDepthOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_EmbeddingLookupSparseOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::EmbeddingLookupSparseOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_MulOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::MulOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_PadOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::PadOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_GatherOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::GatherOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_BatchToSpaceNDOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::BatchToSpaceNDOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_SpaceToBatchNDOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SpaceToBatchNDOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_TransposeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::TransposeOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_ReducerOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ReducerOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_SubOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SubOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_DivOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::DivOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_SqueezeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SqueezeOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_SequenceRNNOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SequenceRNNOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_StridedSliceOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::StridedSliceOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_ExpOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ExpOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_TopKV2Options:
+ {
+ auto ptr = reinterpret_cast<const circle::TopKV2Options *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_SplitOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SplitOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_LogSoftmaxOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LogSoftmaxOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_CastOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::CastOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_DequantizeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::DequantizeOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_MaximumMinimumOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::MaximumMinimumOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_ArgMaxOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ArgMaxOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_LessOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LessOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_NegOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::NegOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_PadV2Options:
+ {
+ auto ptr = reinterpret_cast<const circle::PadV2Options *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_GreaterOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::GreaterOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_GreaterEqualOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::GreaterEqualOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_LessEqualOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LessEqualOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_SelectOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SelectOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_SliceOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SliceOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_TransposeConvOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::TransposeConvOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_SparseToDenseOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SparseToDenseOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_TileOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::TileOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_ExpandDimsOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ExpandDimsOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_EqualOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::EqualOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_NotEqualOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::NotEqualOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_ShapeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ShapeOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_PowOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::PowOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_ArgMinOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ArgMinOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_FakeQuantOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::FakeQuantOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_PackOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::PackOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_LogicalOrOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LogicalOrOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_OneHotOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::OneHotOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_LogicalAndOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LogicalAndOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_LogicalNotOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LogicalNotOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_UnpackOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::UnpackOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_FloorDivOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::FloorDivOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_SquareOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SquareOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_ZerosLikeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ZerosLikeOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_FillOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::FillOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_BidirectionalSequenceLSTMOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::BidirectionalSequenceLSTMOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_BidirectionalSequenceRNNOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::BidirectionalSequenceRNNOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_UnidirectionalSequenceLSTMOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::UnidirectionalSequenceLSTMOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_FloorModOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::FloorModOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_RangeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::RangeOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_ResizeNearestNeighborOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ResizeNearestNeighborOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_LeakyReluOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LeakyReluOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_SquaredDifferenceOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SquaredDifferenceOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_MirrorPadOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::MirrorPadOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_AbsOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::AbsOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_SplitVOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SplitVOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_UniqueOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::UniqueOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_ReverseV2Options:
+ {
+ auto ptr = reinterpret_cast<const circle::ReverseV2Options *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_AddNOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::AddNOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_GatherNdOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::GatherNdOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_CosOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::CosOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_WhereOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::WhereOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_RankOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::RankOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_ReverseSequenceOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ReverseSequenceOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_MatrixDiagOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::MatrixDiagOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_QuantizeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::QuantizeOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_MatrixSetDiagOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::MatrixSetDiagOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_HardSwishOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::HardSwishOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_IfOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::IfOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_WhileOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::WhileOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_DepthToSpaceOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::DepthToSpaceOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_NonMaxSuppressionV4Options:
+ {
+ auto ptr = reinterpret_cast<const circle::NonMaxSuppressionV4Options *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_NonMaxSuppressionV5Options:
+ {
+ auto ptr = reinterpret_cast<const circle::NonMaxSuppressionV5Options *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_ScatterNdOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ScatterNdOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_SelectV2Options:
+ {
+ auto ptr = reinterpret_cast<const circle::SelectV2Options *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_DensifyOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::DensifyOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_SegmentSumOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SegmentSumOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_BatchMatMulOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::BatchMatMulOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_CumsumOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::CumsumOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_CallOnceOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::CallOnceOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_BroadcastToOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::BroadcastToOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_Rfft2dOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::Rfft2dOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_Conv3DOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::Conv3DOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_HashtableOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::HashtableOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_HashtableFindOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::HashtableFindOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_HashtableImportOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::HashtableImportOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_HashtableSizeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::HashtableSizeOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_VarHandleOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::VarHandleOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_ReadVariableOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ReadVariableOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_AssignVariableOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::AssignVariableOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_RandomOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::RandomOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_BCQGatherOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::BCQGatherOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_BCQFullyConnectedOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::BCQFullyConnectedOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_InstanceNormOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::InstanceNormOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ default:
+ return true;
+ }
+}
+
+inline bool VerifyBuiltinOptionsVector(flatbuffers::Verifier &verifier,
+ const flatbuffers::Vector<flatbuffers::Offset<void>> *values,
+ const flatbuffers::Vector<uint8_t> *types)
+{
+ if (!values || !types)
+ return !values && !types;
+ if (values->size() != types->size())
+ return false;
+ for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i)
+ {
+ if (!VerifyBuiltinOptions(verifier, values->Get(i), types->GetEnum<BuiltinOptions>(i)))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+inline void *BuiltinOptionsUnion::UnPack(const void *obj, BuiltinOptions type,
+ const flatbuffers::resolver_function_t *resolver)
+{
+ switch (type)
+ {
+ case BuiltinOptions_Conv2DOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::Conv2DOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_DepthwiseConv2DOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::DepthwiseConv2DOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_ConcatEmbeddingsOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ConcatEmbeddingsOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_LSHProjectionOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LSHProjectionOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_Pool2DOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::Pool2DOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_SVDFOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SVDFOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_RNNOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::RNNOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_FullyConnectedOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::FullyConnectedOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_SoftmaxOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SoftmaxOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_ConcatenationOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ConcatenationOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_AddOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::AddOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_L2NormOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::L2NormOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_LocalResponseNormalizationOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LocalResponseNormalizationOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_LSTMOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LSTMOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_ResizeBilinearOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ResizeBilinearOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_CallOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::CallOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_ReshapeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ReshapeOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_SkipGramOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SkipGramOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_SpaceToDepthOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SpaceToDepthOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_EmbeddingLookupSparseOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::EmbeddingLookupSparseOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_MulOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::MulOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_PadOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::PadOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_GatherOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::GatherOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_BatchToSpaceNDOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::BatchToSpaceNDOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_SpaceToBatchNDOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SpaceToBatchNDOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_TransposeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::TransposeOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_ReducerOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ReducerOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_SubOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SubOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_DivOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::DivOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_SqueezeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SqueezeOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_SequenceRNNOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SequenceRNNOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_StridedSliceOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::StridedSliceOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_ExpOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ExpOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_TopKV2Options:
+ {
+ auto ptr = reinterpret_cast<const circle::TopKV2Options *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_SplitOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SplitOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_LogSoftmaxOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LogSoftmaxOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_CastOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::CastOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_DequantizeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::DequantizeOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_MaximumMinimumOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::MaximumMinimumOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_ArgMaxOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ArgMaxOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_LessOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LessOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_NegOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::NegOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_PadV2Options:
+ {
+ auto ptr = reinterpret_cast<const circle::PadV2Options *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_GreaterOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::GreaterOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_GreaterEqualOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::GreaterEqualOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_LessEqualOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LessEqualOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_SelectOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SelectOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_SliceOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SliceOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_TransposeConvOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::TransposeConvOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_SparseToDenseOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SparseToDenseOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_TileOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::TileOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_ExpandDimsOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ExpandDimsOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_EqualOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::EqualOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_NotEqualOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::NotEqualOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_ShapeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ShapeOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_PowOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::PowOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_ArgMinOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ArgMinOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_FakeQuantOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::FakeQuantOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_PackOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::PackOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_LogicalOrOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LogicalOrOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_OneHotOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::OneHotOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_LogicalAndOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LogicalAndOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_LogicalNotOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LogicalNotOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_UnpackOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::UnpackOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_FloorDivOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::FloorDivOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_SquareOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SquareOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_ZerosLikeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ZerosLikeOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_FillOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::FillOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_BidirectionalSequenceLSTMOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::BidirectionalSequenceLSTMOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_BidirectionalSequenceRNNOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::BidirectionalSequenceRNNOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_UnidirectionalSequenceLSTMOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::UnidirectionalSequenceLSTMOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_FloorModOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::FloorModOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_RangeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::RangeOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_ResizeNearestNeighborOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ResizeNearestNeighborOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_LeakyReluOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LeakyReluOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_SquaredDifferenceOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SquaredDifferenceOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_MirrorPadOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::MirrorPadOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_AbsOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::AbsOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_SplitVOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SplitVOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_UniqueOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::UniqueOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_ReverseV2Options:
+ {
+ auto ptr = reinterpret_cast<const circle::ReverseV2Options *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_AddNOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::AddNOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_GatherNdOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::GatherNdOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_CosOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::CosOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_WhereOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::WhereOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_RankOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::RankOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_ReverseSequenceOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ReverseSequenceOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_MatrixDiagOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::MatrixDiagOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_QuantizeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::QuantizeOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_MatrixSetDiagOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::MatrixSetDiagOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_HardSwishOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::HardSwishOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_IfOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::IfOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_WhileOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::WhileOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_DepthToSpaceOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::DepthToSpaceOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_NonMaxSuppressionV4Options:
+ {
+ auto ptr = reinterpret_cast<const circle::NonMaxSuppressionV4Options *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_NonMaxSuppressionV5Options:
+ {
+ auto ptr = reinterpret_cast<const circle::NonMaxSuppressionV5Options *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_ScatterNdOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ScatterNdOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_SelectV2Options:
+ {
+ auto ptr = reinterpret_cast<const circle::SelectV2Options *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_DensifyOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::DensifyOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_SegmentSumOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SegmentSumOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_BatchMatMulOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::BatchMatMulOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_CumsumOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::CumsumOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_CallOnceOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::CallOnceOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_BroadcastToOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::BroadcastToOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_Rfft2dOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::Rfft2dOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_Conv3DOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::Conv3DOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_HashtableOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::HashtableOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_HashtableFindOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::HashtableFindOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_HashtableImportOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::HashtableImportOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_HashtableSizeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::HashtableSizeOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_VarHandleOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::VarHandleOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_ReadVariableOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ReadVariableOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_AssignVariableOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::AssignVariableOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_RandomOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::RandomOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_BCQGatherOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::BCQGatherOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_BCQFullyConnectedOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::BCQFullyConnectedOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ case BuiltinOptions_InstanceNormOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::InstanceNormOptions *>(obj);
+ return ptr->UnPack(resolver);
+ }
+ default:
+ return nullptr;
+ }
+}
+
+inline flatbuffers::Offset<void>
+BuiltinOptionsUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+ const flatbuffers::rehasher_function_t *_rehasher) const
+{
+ switch (type)
+ {
+ case BuiltinOptions_Conv2DOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::Conv2DOptionsT *>(value);
+ return CreateConv2DOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_DepthwiseConv2DOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::DepthwiseConv2DOptionsT *>(value);
+ return CreateDepthwiseConv2DOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_ConcatEmbeddingsOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ConcatEmbeddingsOptionsT *>(value);
+ return CreateConcatEmbeddingsOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_LSHProjectionOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LSHProjectionOptionsT *>(value);
+ return CreateLSHProjectionOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_Pool2DOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::Pool2DOptionsT *>(value);
+ return CreatePool2DOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_SVDFOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SVDFOptionsT *>(value);
+ return CreateSVDFOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_RNNOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::RNNOptionsT *>(value);
+ return CreateRNNOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_FullyConnectedOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::FullyConnectedOptionsT *>(value);
+ return CreateFullyConnectedOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_SoftmaxOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SoftmaxOptionsT *>(value);
+ return CreateSoftmaxOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_ConcatenationOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ConcatenationOptionsT *>(value);
+ return CreateConcatenationOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_AddOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::AddOptionsT *>(value);
+ return CreateAddOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_L2NormOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::L2NormOptionsT *>(value);
+ return CreateL2NormOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_LocalResponseNormalizationOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LocalResponseNormalizationOptionsT *>(value);
+ return CreateLocalResponseNormalizationOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_LSTMOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LSTMOptionsT *>(value);
+ return CreateLSTMOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_ResizeBilinearOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ResizeBilinearOptionsT *>(value);
+ return CreateResizeBilinearOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_CallOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::CallOptionsT *>(value);
+ return CreateCallOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_ReshapeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ReshapeOptionsT *>(value);
+ return CreateReshapeOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_SkipGramOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SkipGramOptionsT *>(value);
+ return CreateSkipGramOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_SpaceToDepthOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SpaceToDepthOptionsT *>(value);
+ return CreateSpaceToDepthOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_EmbeddingLookupSparseOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::EmbeddingLookupSparseOptionsT *>(value);
+ return CreateEmbeddingLookupSparseOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_MulOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::MulOptionsT *>(value);
+ return CreateMulOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_PadOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::PadOptionsT *>(value);
+ return CreatePadOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_GatherOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::GatherOptionsT *>(value);
+ return CreateGatherOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_BatchToSpaceNDOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::BatchToSpaceNDOptionsT *>(value);
+ return CreateBatchToSpaceNDOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_SpaceToBatchNDOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SpaceToBatchNDOptionsT *>(value);
+ return CreateSpaceToBatchNDOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_TransposeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::TransposeOptionsT *>(value);
+ return CreateTransposeOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_ReducerOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ReducerOptionsT *>(value);
+ return CreateReducerOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_SubOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SubOptionsT *>(value);
+ return CreateSubOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_DivOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::DivOptionsT *>(value);
+ return CreateDivOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_SqueezeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SqueezeOptionsT *>(value);
+ return CreateSqueezeOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_SequenceRNNOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SequenceRNNOptionsT *>(value);
+ return CreateSequenceRNNOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_StridedSliceOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::StridedSliceOptionsT *>(value);
+ return CreateStridedSliceOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_ExpOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ExpOptionsT *>(value);
+ return CreateExpOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_TopKV2Options:
+ {
+ auto ptr = reinterpret_cast<const circle::TopKV2OptionsT *>(value);
+ return CreateTopKV2Options(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_SplitOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SplitOptionsT *>(value);
+ return CreateSplitOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_LogSoftmaxOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LogSoftmaxOptionsT *>(value);
+ return CreateLogSoftmaxOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_CastOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::CastOptionsT *>(value);
+ return CreateCastOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_DequantizeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::DequantizeOptionsT *>(value);
+ return CreateDequantizeOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_MaximumMinimumOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::MaximumMinimumOptionsT *>(value);
+ return CreateMaximumMinimumOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_ArgMaxOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ArgMaxOptionsT *>(value);
+ return CreateArgMaxOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_LessOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LessOptionsT *>(value);
+ return CreateLessOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_NegOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::NegOptionsT *>(value);
+ return CreateNegOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_PadV2Options:
+ {
+ auto ptr = reinterpret_cast<const circle::PadV2OptionsT *>(value);
+ return CreatePadV2Options(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_GreaterOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::GreaterOptionsT *>(value);
+ return CreateGreaterOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_GreaterEqualOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::GreaterEqualOptionsT *>(value);
+ return CreateGreaterEqualOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_LessEqualOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LessEqualOptionsT *>(value);
+ return CreateLessEqualOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_SelectOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SelectOptionsT *>(value);
+ return CreateSelectOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_SliceOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SliceOptionsT *>(value);
+ return CreateSliceOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_TransposeConvOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::TransposeConvOptionsT *>(value);
+ return CreateTransposeConvOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_SparseToDenseOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SparseToDenseOptionsT *>(value);
+ return CreateSparseToDenseOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_TileOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::TileOptionsT *>(value);
+ return CreateTileOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_ExpandDimsOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ExpandDimsOptionsT *>(value);
+ return CreateExpandDimsOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_EqualOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::EqualOptionsT *>(value);
+ return CreateEqualOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_NotEqualOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::NotEqualOptionsT *>(value);
+ return CreateNotEqualOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_ShapeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ShapeOptionsT *>(value);
+ return CreateShapeOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_PowOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::PowOptionsT *>(value);
+ return CreatePowOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_ArgMinOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ArgMinOptionsT *>(value);
+ return CreateArgMinOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_FakeQuantOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::FakeQuantOptionsT *>(value);
+ return CreateFakeQuantOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_PackOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::PackOptionsT *>(value);
+ return CreatePackOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_LogicalOrOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LogicalOrOptionsT *>(value);
+ return CreateLogicalOrOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_OneHotOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::OneHotOptionsT *>(value);
+ return CreateOneHotOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_LogicalAndOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LogicalAndOptionsT *>(value);
+ return CreateLogicalAndOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_LogicalNotOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LogicalNotOptionsT *>(value);
+ return CreateLogicalNotOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_UnpackOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::UnpackOptionsT *>(value);
+ return CreateUnpackOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_FloorDivOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::FloorDivOptionsT *>(value);
+ return CreateFloorDivOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_SquareOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SquareOptionsT *>(value);
+ return CreateSquareOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_ZerosLikeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ZerosLikeOptionsT *>(value);
+ return CreateZerosLikeOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_FillOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::FillOptionsT *>(value);
+ return CreateFillOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_BidirectionalSequenceLSTMOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::BidirectionalSequenceLSTMOptionsT *>(value);
+ return CreateBidirectionalSequenceLSTMOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_BidirectionalSequenceRNNOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::BidirectionalSequenceRNNOptionsT *>(value);
+ return CreateBidirectionalSequenceRNNOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_UnidirectionalSequenceLSTMOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::UnidirectionalSequenceLSTMOptionsT *>(value);
+ return CreateUnidirectionalSequenceLSTMOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_FloorModOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::FloorModOptionsT *>(value);
+ return CreateFloorModOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_RangeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::RangeOptionsT *>(value);
+ return CreateRangeOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_ResizeNearestNeighborOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ResizeNearestNeighborOptionsT *>(value);
+ return CreateResizeNearestNeighborOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_LeakyReluOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::LeakyReluOptionsT *>(value);
+ return CreateLeakyReluOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_SquaredDifferenceOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SquaredDifferenceOptionsT *>(value);
+ return CreateSquaredDifferenceOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_MirrorPadOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::MirrorPadOptionsT *>(value);
+ return CreateMirrorPadOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_AbsOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::AbsOptionsT *>(value);
+ return CreateAbsOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_SplitVOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SplitVOptionsT *>(value);
+ return CreateSplitVOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_UniqueOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::UniqueOptionsT *>(value);
+ return CreateUniqueOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_ReverseV2Options:
+ {
+ auto ptr = reinterpret_cast<const circle::ReverseV2OptionsT *>(value);
+ return CreateReverseV2Options(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_AddNOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::AddNOptionsT *>(value);
+ return CreateAddNOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_GatherNdOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::GatherNdOptionsT *>(value);
+ return CreateGatherNdOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_CosOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::CosOptionsT *>(value);
+ return CreateCosOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_WhereOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::WhereOptionsT *>(value);
+ return CreateWhereOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_RankOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::RankOptionsT *>(value);
+ return CreateRankOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_ReverseSequenceOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ReverseSequenceOptionsT *>(value);
+ return CreateReverseSequenceOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_MatrixDiagOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::MatrixDiagOptionsT *>(value);
+ return CreateMatrixDiagOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_QuantizeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::QuantizeOptionsT *>(value);
+ return CreateQuantizeOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_MatrixSetDiagOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::MatrixSetDiagOptionsT *>(value);
+ return CreateMatrixSetDiagOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_HardSwishOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::HardSwishOptionsT *>(value);
+ return CreateHardSwishOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_IfOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::IfOptionsT *>(value);
+ return CreateIfOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_WhileOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::WhileOptionsT *>(value);
+ return CreateWhileOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_DepthToSpaceOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::DepthToSpaceOptionsT *>(value);
+ return CreateDepthToSpaceOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_NonMaxSuppressionV4Options:
+ {
+ auto ptr = reinterpret_cast<const circle::NonMaxSuppressionV4OptionsT *>(value);
+ return CreateNonMaxSuppressionV4Options(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_NonMaxSuppressionV5Options:
+ {
+ auto ptr = reinterpret_cast<const circle::NonMaxSuppressionV5OptionsT *>(value);
+ return CreateNonMaxSuppressionV5Options(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_ScatterNdOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ScatterNdOptionsT *>(value);
+ return CreateScatterNdOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_SelectV2Options:
+ {
+ auto ptr = reinterpret_cast<const circle::SelectV2OptionsT *>(value);
+ return CreateSelectV2Options(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_DensifyOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::DensifyOptionsT *>(value);
+ return CreateDensifyOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_SegmentSumOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SegmentSumOptionsT *>(value);
+ return CreateSegmentSumOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_BatchMatMulOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::BatchMatMulOptionsT *>(value);
+ return CreateBatchMatMulOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_CumsumOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::CumsumOptionsT *>(value);
+ return CreateCumsumOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_CallOnceOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::CallOnceOptionsT *>(value);
+ return CreateCallOnceOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_BroadcastToOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::BroadcastToOptionsT *>(value);
+ return CreateBroadcastToOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_Rfft2dOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::Rfft2dOptionsT *>(value);
+ return CreateRfft2dOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_Conv3DOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::Conv3DOptionsT *>(value);
+ return CreateConv3DOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_HashtableOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::HashtableOptionsT *>(value);
+ return CreateHashtableOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_HashtableFindOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::HashtableFindOptionsT *>(value);
+ return CreateHashtableFindOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_HashtableImportOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::HashtableImportOptionsT *>(value);
+ return CreateHashtableImportOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_HashtableSizeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::HashtableSizeOptionsT *>(value);
+ return CreateHashtableSizeOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_VarHandleOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::VarHandleOptionsT *>(value);
+ return CreateVarHandleOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_ReadVariableOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::ReadVariableOptionsT *>(value);
+ return CreateReadVariableOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_AssignVariableOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::AssignVariableOptionsT *>(value);
+ return CreateAssignVariableOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_RandomOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::RandomOptionsT *>(value);
+ return CreateRandomOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_BCQGatherOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::BCQGatherOptionsT *>(value);
+ return CreateBCQGatherOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_BCQFullyConnectedOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::BCQFullyConnectedOptionsT *>(value);
+ return CreateBCQFullyConnectedOptions(_fbb, ptr, _rehasher).Union();
+ }
+ case BuiltinOptions_InstanceNormOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::InstanceNormOptionsT *>(value);
+ return CreateInstanceNormOptions(_fbb, ptr, _rehasher).Union();
+ }
+ default:
+ return 0;
+ }
+}
+
+inline BuiltinOptionsUnion::BuiltinOptionsUnion(const BuiltinOptionsUnion &u)
+ : type(u.type), value(nullptr)
+{
+ switch (type)
+ {
+ case BuiltinOptions_Conv2DOptions:
+ {
+ value = new circle::Conv2DOptionsT(*reinterpret_cast<circle::Conv2DOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_DepthwiseConv2DOptions:
+ {
+ value = new circle::DepthwiseConv2DOptionsT(
+ *reinterpret_cast<circle::DepthwiseConv2DOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_ConcatEmbeddingsOptions:
+ {
+ value = new circle::ConcatEmbeddingsOptionsT(
+ *reinterpret_cast<circle::ConcatEmbeddingsOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_LSHProjectionOptions:
+ {
+ value = new circle::LSHProjectionOptionsT(
+ *reinterpret_cast<circle::LSHProjectionOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_Pool2DOptions:
+ {
+ value = new circle::Pool2DOptionsT(*reinterpret_cast<circle::Pool2DOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_SVDFOptions:
+ {
+ value = new circle::SVDFOptionsT(*reinterpret_cast<circle::SVDFOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_RNNOptions:
+ {
+ value = new circle::RNNOptionsT(*reinterpret_cast<circle::RNNOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_FullyConnectedOptions:
+ {
+ value = new circle::FullyConnectedOptionsT(
+ *reinterpret_cast<circle::FullyConnectedOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_SoftmaxOptions:
+ {
+ value = new circle::SoftmaxOptionsT(*reinterpret_cast<circle::SoftmaxOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_ConcatenationOptions:
+ {
+ value = new circle::ConcatenationOptionsT(
+ *reinterpret_cast<circle::ConcatenationOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_AddOptions:
+ {
+ value = new circle::AddOptionsT(*reinterpret_cast<circle::AddOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_L2NormOptions:
+ {
+ value = new circle::L2NormOptionsT(*reinterpret_cast<circle::L2NormOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_LocalResponseNormalizationOptions:
+ {
+ value = new circle::LocalResponseNormalizationOptionsT(
+ *reinterpret_cast<circle::LocalResponseNormalizationOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_LSTMOptions:
+ {
+ value = new circle::LSTMOptionsT(*reinterpret_cast<circle::LSTMOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_ResizeBilinearOptions:
+ {
+ value = new circle::ResizeBilinearOptionsT(
+ *reinterpret_cast<circle::ResizeBilinearOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_CallOptions:
+ {
+ value = new circle::CallOptionsT(*reinterpret_cast<circle::CallOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_ReshapeOptions:
+ {
+ value = new circle::ReshapeOptionsT(*reinterpret_cast<circle::ReshapeOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_SkipGramOptions:
+ {
+ value = new circle::SkipGramOptionsT(*reinterpret_cast<circle::SkipGramOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_SpaceToDepthOptions:
+ {
+ value = new circle::SpaceToDepthOptionsT(
+ *reinterpret_cast<circle::SpaceToDepthOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_EmbeddingLookupSparseOptions:
+ {
+ value = new circle::EmbeddingLookupSparseOptionsT(
+ *reinterpret_cast<circle::EmbeddingLookupSparseOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_MulOptions:
+ {
+ value = new circle::MulOptionsT(*reinterpret_cast<circle::MulOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_PadOptions:
+ {
+ value = new circle::PadOptionsT(*reinterpret_cast<circle::PadOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_GatherOptions:
+ {
+ value = new circle::GatherOptionsT(*reinterpret_cast<circle::GatherOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_BatchToSpaceNDOptions:
+ {
+ value = new circle::BatchToSpaceNDOptionsT(
+ *reinterpret_cast<circle::BatchToSpaceNDOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_SpaceToBatchNDOptions:
+ {
+ value = new circle::SpaceToBatchNDOptionsT(
+ *reinterpret_cast<circle::SpaceToBatchNDOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_TransposeOptions:
+ {
+ value =
+ new circle::TransposeOptionsT(*reinterpret_cast<circle::TransposeOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_ReducerOptions:
+ {
+ value = new circle::ReducerOptionsT(*reinterpret_cast<circle::ReducerOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_SubOptions:
+ {
+ value = new circle::SubOptionsT(*reinterpret_cast<circle::SubOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_DivOptions:
+ {
+ value = new circle::DivOptionsT(*reinterpret_cast<circle::DivOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_SqueezeOptions:
+ {
+ value = new circle::SqueezeOptionsT(*reinterpret_cast<circle::SqueezeOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_SequenceRNNOptions:
+ {
+ value =
+ new circle::SequenceRNNOptionsT(*reinterpret_cast<circle::SequenceRNNOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_StridedSliceOptions:
+ {
+ value = new circle::StridedSliceOptionsT(
+ *reinterpret_cast<circle::StridedSliceOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_ExpOptions:
+ {
+ value = new circle::ExpOptionsT(*reinterpret_cast<circle::ExpOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_TopKV2Options:
+ {
+ value = new circle::TopKV2OptionsT(*reinterpret_cast<circle::TopKV2OptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_SplitOptions:
+ {
+ value = new circle::SplitOptionsT(*reinterpret_cast<circle::SplitOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_LogSoftmaxOptions:
+ {
+ value =
+ new circle::LogSoftmaxOptionsT(*reinterpret_cast<circle::LogSoftmaxOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_CastOptions:
+ {
+ value = new circle::CastOptionsT(*reinterpret_cast<circle::CastOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_DequantizeOptions:
+ {
+ value =
+ new circle::DequantizeOptionsT(*reinterpret_cast<circle::DequantizeOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_MaximumMinimumOptions:
+ {
+ value = new circle::MaximumMinimumOptionsT(
+ *reinterpret_cast<circle::MaximumMinimumOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_ArgMaxOptions:
+ {
+ value = new circle::ArgMaxOptionsT(*reinterpret_cast<circle::ArgMaxOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_LessOptions:
+ {
+ value = new circle::LessOptionsT(*reinterpret_cast<circle::LessOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_NegOptions:
+ {
+ value = new circle::NegOptionsT(*reinterpret_cast<circle::NegOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_PadV2Options:
+ {
+ value = new circle::PadV2OptionsT(*reinterpret_cast<circle::PadV2OptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_GreaterOptions:
+ {
+ value = new circle::GreaterOptionsT(*reinterpret_cast<circle::GreaterOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_GreaterEqualOptions:
+ {
+ value = new circle::GreaterEqualOptionsT(
+ *reinterpret_cast<circle::GreaterEqualOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_LessEqualOptions:
+ {
+ value =
+ new circle::LessEqualOptionsT(*reinterpret_cast<circle::LessEqualOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_SelectOptions:
+ {
+ value = new circle::SelectOptionsT(*reinterpret_cast<circle::SelectOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_SliceOptions:
+ {
+ value = new circle::SliceOptionsT(*reinterpret_cast<circle::SliceOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_TransposeConvOptions:
+ {
+ value = new circle::TransposeConvOptionsT(
+ *reinterpret_cast<circle::TransposeConvOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_SparseToDenseOptions:
+ {
+ value = new circle::SparseToDenseOptionsT(
+ *reinterpret_cast<circle::SparseToDenseOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_TileOptions:
+ {
+ value = new circle::TileOptionsT(*reinterpret_cast<circle::TileOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_ExpandDimsOptions:
+ {
+ value =
+ new circle::ExpandDimsOptionsT(*reinterpret_cast<circle::ExpandDimsOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_EqualOptions:
+ {
+ value = new circle::EqualOptionsT(*reinterpret_cast<circle::EqualOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_NotEqualOptions:
+ {
+ value = new circle::NotEqualOptionsT(*reinterpret_cast<circle::NotEqualOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_ShapeOptions:
+ {
+ value = new circle::ShapeOptionsT(*reinterpret_cast<circle::ShapeOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_PowOptions:
+ {
+ value = new circle::PowOptionsT(*reinterpret_cast<circle::PowOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_ArgMinOptions:
+ {
+ value = new circle::ArgMinOptionsT(*reinterpret_cast<circle::ArgMinOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_FakeQuantOptions:
+ {
+ value =
+ new circle::FakeQuantOptionsT(*reinterpret_cast<circle::FakeQuantOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_PackOptions:
+ {
+ value = new circle::PackOptionsT(*reinterpret_cast<circle::PackOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_LogicalOrOptions:
+ {
+ value =
+ new circle::LogicalOrOptionsT(*reinterpret_cast<circle::LogicalOrOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_OneHotOptions:
+ {
+ value = new circle::OneHotOptionsT(*reinterpret_cast<circle::OneHotOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_LogicalAndOptions:
+ {
+ value =
+ new circle::LogicalAndOptionsT(*reinterpret_cast<circle::LogicalAndOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_LogicalNotOptions:
+ {
+ value =
+ new circle::LogicalNotOptionsT(*reinterpret_cast<circle::LogicalNotOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_UnpackOptions:
+ {
+ value = new circle::UnpackOptionsT(*reinterpret_cast<circle::UnpackOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_FloorDivOptions:
+ {
+ value = new circle::FloorDivOptionsT(*reinterpret_cast<circle::FloorDivOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_SquareOptions:
+ {
+ value = new circle::SquareOptionsT(*reinterpret_cast<circle::SquareOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_ZerosLikeOptions:
+ {
+ value =
+ new circle::ZerosLikeOptionsT(*reinterpret_cast<circle::ZerosLikeOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_FillOptions:
+ {
+ value = new circle::FillOptionsT(*reinterpret_cast<circle::FillOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_BidirectionalSequenceLSTMOptions:
+ {
+ value = new circle::BidirectionalSequenceLSTMOptionsT(
+ *reinterpret_cast<circle::BidirectionalSequenceLSTMOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_BidirectionalSequenceRNNOptions:
+ {
+ value = new circle::BidirectionalSequenceRNNOptionsT(
+ *reinterpret_cast<circle::BidirectionalSequenceRNNOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_UnidirectionalSequenceLSTMOptions:
+ {
+ value = new circle::UnidirectionalSequenceLSTMOptionsT(
+ *reinterpret_cast<circle::UnidirectionalSequenceLSTMOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_FloorModOptions:
+ {
+ value = new circle::FloorModOptionsT(*reinterpret_cast<circle::FloorModOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_RangeOptions:
+ {
+ value = new circle::RangeOptionsT(*reinterpret_cast<circle::RangeOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_ResizeNearestNeighborOptions:
+ {
+ value = new circle::ResizeNearestNeighborOptionsT(
+ *reinterpret_cast<circle::ResizeNearestNeighborOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_LeakyReluOptions:
+ {
+ value =
+ new circle::LeakyReluOptionsT(*reinterpret_cast<circle::LeakyReluOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_SquaredDifferenceOptions:
+ {
+ value = new circle::SquaredDifferenceOptionsT(
+ *reinterpret_cast<circle::SquaredDifferenceOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_MirrorPadOptions:
+ {
+ value =
+ new circle::MirrorPadOptionsT(*reinterpret_cast<circle::MirrorPadOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_AbsOptions:
+ {
+ value = new circle::AbsOptionsT(*reinterpret_cast<circle::AbsOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_SplitVOptions:
+ {
+ value = new circle::SplitVOptionsT(*reinterpret_cast<circle::SplitVOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_UniqueOptions:
+ {
+ value = new circle::UniqueOptionsT(*reinterpret_cast<circle::UniqueOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_ReverseV2Options:
+ {
+ value =
+ new circle::ReverseV2OptionsT(*reinterpret_cast<circle::ReverseV2OptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_AddNOptions:
+ {
+ value = new circle::AddNOptionsT(*reinterpret_cast<circle::AddNOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_GatherNdOptions:
+ {
+ value = new circle::GatherNdOptionsT(*reinterpret_cast<circle::GatherNdOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_CosOptions:
+ {
+ value = new circle::CosOptionsT(*reinterpret_cast<circle::CosOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_WhereOptions:
+ {
+ value = new circle::WhereOptionsT(*reinterpret_cast<circle::WhereOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_RankOptions:
+ {
+ value = new circle::RankOptionsT(*reinterpret_cast<circle::RankOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_ReverseSequenceOptions:
+ {
+ value = new circle::ReverseSequenceOptionsT(
+ *reinterpret_cast<circle::ReverseSequenceOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_MatrixDiagOptions:
+ {
+ value =
+ new circle::MatrixDiagOptionsT(*reinterpret_cast<circle::MatrixDiagOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_QuantizeOptions:
+ {
+ value = new circle::QuantizeOptionsT(*reinterpret_cast<circle::QuantizeOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_MatrixSetDiagOptions:
+ {
+ value = new circle::MatrixSetDiagOptionsT(
+ *reinterpret_cast<circle::MatrixSetDiagOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_HardSwishOptions:
+ {
+ value =
+ new circle::HardSwishOptionsT(*reinterpret_cast<circle::HardSwishOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_IfOptions:
+ {
+ value = new circle::IfOptionsT(*reinterpret_cast<circle::IfOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_WhileOptions:
+ {
+ value = new circle::WhileOptionsT(*reinterpret_cast<circle::WhileOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_DepthToSpaceOptions:
+ {
+ value = new circle::DepthToSpaceOptionsT(
+ *reinterpret_cast<circle::DepthToSpaceOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_NonMaxSuppressionV4Options:
+ {
+ value = new circle::NonMaxSuppressionV4OptionsT(
+ *reinterpret_cast<circle::NonMaxSuppressionV4OptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_NonMaxSuppressionV5Options:
+ {
+ value = new circle::NonMaxSuppressionV5OptionsT(
+ *reinterpret_cast<circle::NonMaxSuppressionV5OptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_ScatterNdOptions:
+ {
+ value =
+ new circle::ScatterNdOptionsT(*reinterpret_cast<circle::ScatterNdOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_SelectV2Options:
+ {
+ value = new circle::SelectV2OptionsT(*reinterpret_cast<circle::SelectV2OptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_DensifyOptions:
+ {
+ value = new circle::DensifyOptionsT(*reinterpret_cast<circle::DensifyOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_SegmentSumOptions:
+ {
+ value =
+ new circle::SegmentSumOptionsT(*reinterpret_cast<circle::SegmentSumOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_BatchMatMulOptions:
+ {
+ value =
+ new circle::BatchMatMulOptionsT(*reinterpret_cast<circle::BatchMatMulOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_CumsumOptions:
+ {
+ value = new circle::CumsumOptionsT(*reinterpret_cast<circle::CumsumOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_CallOnceOptions:
+ {
+ value = new circle::CallOnceOptionsT(*reinterpret_cast<circle::CallOnceOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_BroadcastToOptions:
+ {
+ value =
+ new circle::BroadcastToOptionsT(*reinterpret_cast<circle::BroadcastToOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_Rfft2dOptions:
+ {
+ value = new circle::Rfft2dOptionsT(*reinterpret_cast<circle::Rfft2dOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_Conv3DOptions:
+ {
+ value = new circle::Conv3DOptionsT(*reinterpret_cast<circle::Conv3DOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_HashtableOptions:
+ {
+ value =
+ new circle::HashtableOptionsT(*reinterpret_cast<circle::HashtableOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_HashtableFindOptions:
+ {
+ value = new circle::HashtableFindOptionsT(
+ *reinterpret_cast<circle::HashtableFindOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_HashtableImportOptions:
+ {
+ value = new circle::HashtableImportOptionsT(
+ *reinterpret_cast<circle::HashtableImportOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_HashtableSizeOptions:
+ {
+ value = new circle::HashtableSizeOptionsT(
+ *reinterpret_cast<circle::HashtableSizeOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_VarHandleOptions:
+ {
+ value =
+ new circle::VarHandleOptionsT(*reinterpret_cast<circle::VarHandleOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_ReadVariableOptions:
+ {
+ value = new circle::ReadVariableOptionsT(
+ *reinterpret_cast<circle::ReadVariableOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_AssignVariableOptions:
+ {
+ value = new circle::AssignVariableOptionsT(
+ *reinterpret_cast<circle::AssignVariableOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_RandomOptions:
+ {
+ value = new circle::RandomOptionsT(*reinterpret_cast<circle::RandomOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_BCQGatherOptions:
+ {
+ value =
+ new circle::BCQGatherOptionsT(*reinterpret_cast<circle::BCQGatherOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_BCQFullyConnectedOptions:
+ {
+ value = new circle::BCQFullyConnectedOptionsT(
+ *reinterpret_cast<circle::BCQFullyConnectedOptionsT *>(u.value));
+ break;
+ }
+ case BuiltinOptions_InstanceNormOptions:
+ {
+ value = new circle::InstanceNormOptionsT(
+ *reinterpret_cast<circle::InstanceNormOptionsT *>(u.value));
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+inline void BuiltinOptionsUnion::Reset()
+{
+ switch (type)
+ {
+ case BuiltinOptions_Conv2DOptions:
+ {
+ auto ptr = reinterpret_cast<circle::Conv2DOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_DepthwiseConv2DOptions:
+ {
+ auto ptr = reinterpret_cast<circle::DepthwiseConv2DOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_ConcatEmbeddingsOptions:
+ {
+ auto ptr = reinterpret_cast<circle::ConcatEmbeddingsOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_LSHProjectionOptions:
+ {
+ auto ptr = reinterpret_cast<circle::LSHProjectionOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_Pool2DOptions:
+ {
+ auto ptr = reinterpret_cast<circle::Pool2DOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_SVDFOptions:
+ {
+ auto ptr = reinterpret_cast<circle::SVDFOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_RNNOptions:
+ {
+ auto ptr = reinterpret_cast<circle::RNNOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_FullyConnectedOptions:
+ {
+ auto ptr = reinterpret_cast<circle::FullyConnectedOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_SoftmaxOptions:
+ {
+ auto ptr = reinterpret_cast<circle::SoftmaxOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_ConcatenationOptions:
+ {
+ auto ptr = reinterpret_cast<circle::ConcatenationOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_AddOptions:
+ {
+ auto ptr = reinterpret_cast<circle::AddOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_L2NormOptions:
+ {
+ auto ptr = reinterpret_cast<circle::L2NormOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_LocalResponseNormalizationOptions:
+ {
+ auto ptr = reinterpret_cast<circle::LocalResponseNormalizationOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_LSTMOptions:
+ {
+ auto ptr = reinterpret_cast<circle::LSTMOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_ResizeBilinearOptions:
+ {
+ auto ptr = reinterpret_cast<circle::ResizeBilinearOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_CallOptions:
+ {
+ auto ptr = reinterpret_cast<circle::CallOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_ReshapeOptions:
+ {
+ auto ptr = reinterpret_cast<circle::ReshapeOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_SkipGramOptions:
+ {
+ auto ptr = reinterpret_cast<circle::SkipGramOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_SpaceToDepthOptions:
+ {
+ auto ptr = reinterpret_cast<circle::SpaceToDepthOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_EmbeddingLookupSparseOptions:
+ {
+ auto ptr = reinterpret_cast<circle::EmbeddingLookupSparseOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_MulOptions:
+ {
+ auto ptr = reinterpret_cast<circle::MulOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_PadOptions:
+ {
+ auto ptr = reinterpret_cast<circle::PadOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_GatherOptions:
+ {
+ auto ptr = reinterpret_cast<circle::GatherOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_BatchToSpaceNDOptions:
+ {
+ auto ptr = reinterpret_cast<circle::BatchToSpaceNDOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_SpaceToBatchNDOptions:
+ {
+ auto ptr = reinterpret_cast<circle::SpaceToBatchNDOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_TransposeOptions:
+ {
+ auto ptr = reinterpret_cast<circle::TransposeOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_ReducerOptions:
+ {
+ auto ptr = reinterpret_cast<circle::ReducerOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_SubOptions:
+ {
+ auto ptr = reinterpret_cast<circle::SubOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_DivOptions:
+ {
+ auto ptr = reinterpret_cast<circle::DivOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_SqueezeOptions:
+ {
+ auto ptr = reinterpret_cast<circle::SqueezeOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_SequenceRNNOptions:
+ {
+ auto ptr = reinterpret_cast<circle::SequenceRNNOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_StridedSliceOptions:
+ {
+ auto ptr = reinterpret_cast<circle::StridedSliceOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_ExpOptions:
+ {
+ auto ptr = reinterpret_cast<circle::ExpOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_TopKV2Options:
+ {
+ auto ptr = reinterpret_cast<circle::TopKV2OptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_SplitOptions:
+ {
+ auto ptr = reinterpret_cast<circle::SplitOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_LogSoftmaxOptions:
+ {
+ auto ptr = reinterpret_cast<circle::LogSoftmaxOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_CastOptions:
+ {
+ auto ptr = reinterpret_cast<circle::CastOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_DequantizeOptions:
+ {
+ auto ptr = reinterpret_cast<circle::DequantizeOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_MaximumMinimumOptions:
+ {
+ auto ptr = reinterpret_cast<circle::MaximumMinimumOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_ArgMaxOptions:
+ {
+ auto ptr = reinterpret_cast<circle::ArgMaxOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_LessOptions:
+ {
+ auto ptr = reinterpret_cast<circle::LessOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_NegOptions:
+ {
+ auto ptr = reinterpret_cast<circle::NegOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_PadV2Options:
+ {
+ auto ptr = reinterpret_cast<circle::PadV2OptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_GreaterOptions:
+ {
+ auto ptr = reinterpret_cast<circle::GreaterOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_GreaterEqualOptions:
+ {
+ auto ptr = reinterpret_cast<circle::GreaterEqualOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_LessEqualOptions:
+ {
+ auto ptr = reinterpret_cast<circle::LessEqualOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_SelectOptions:
+ {
+ auto ptr = reinterpret_cast<circle::SelectOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_SliceOptions:
+ {
+ auto ptr = reinterpret_cast<circle::SliceOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_TransposeConvOptions:
+ {
+ auto ptr = reinterpret_cast<circle::TransposeConvOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_SparseToDenseOptions:
+ {
+ auto ptr = reinterpret_cast<circle::SparseToDenseOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_TileOptions:
+ {
+ auto ptr = reinterpret_cast<circle::TileOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_ExpandDimsOptions:
+ {
+ auto ptr = reinterpret_cast<circle::ExpandDimsOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_EqualOptions:
+ {
+ auto ptr = reinterpret_cast<circle::EqualOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_NotEqualOptions:
+ {
+ auto ptr = reinterpret_cast<circle::NotEqualOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_ShapeOptions:
+ {
+ auto ptr = reinterpret_cast<circle::ShapeOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_PowOptions:
+ {
+ auto ptr = reinterpret_cast<circle::PowOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_ArgMinOptions:
+ {
+ auto ptr = reinterpret_cast<circle::ArgMinOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_FakeQuantOptions:
+ {
+ auto ptr = reinterpret_cast<circle::FakeQuantOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_PackOptions:
+ {
+ auto ptr = reinterpret_cast<circle::PackOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_LogicalOrOptions:
+ {
+ auto ptr = reinterpret_cast<circle::LogicalOrOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_OneHotOptions:
+ {
+ auto ptr = reinterpret_cast<circle::OneHotOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_LogicalAndOptions:
+ {
+ auto ptr = reinterpret_cast<circle::LogicalAndOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_LogicalNotOptions:
+ {
+ auto ptr = reinterpret_cast<circle::LogicalNotOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_UnpackOptions:
+ {
+ auto ptr = reinterpret_cast<circle::UnpackOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_FloorDivOptions:
+ {
+ auto ptr = reinterpret_cast<circle::FloorDivOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_SquareOptions:
+ {
+ auto ptr = reinterpret_cast<circle::SquareOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_ZerosLikeOptions:
+ {
+ auto ptr = reinterpret_cast<circle::ZerosLikeOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_FillOptions:
+ {
+ auto ptr = reinterpret_cast<circle::FillOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_BidirectionalSequenceLSTMOptions:
+ {
+ auto ptr = reinterpret_cast<circle::BidirectionalSequenceLSTMOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_BidirectionalSequenceRNNOptions:
+ {
+ auto ptr = reinterpret_cast<circle::BidirectionalSequenceRNNOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_UnidirectionalSequenceLSTMOptions:
+ {
+ auto ptr = reinterpret_cast<circle::UnidirectionalSequenceLSTMOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_FloorModOptions:
+ {
+ auto ptr = reinterpret_cast<circle::FloorModOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_RangeOptions:
+ {
+ auto ptr = reinterpret_cast<circle::RangeOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_ResizeNearestNeighborOptions:
+ {
+ auto ptr = reinterpret_cast<circle::ResizeNearestNeighborOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_LeakyReluOptions:
+ {
+ auto ptr = reinterpret_cast<circle::LeakyReluOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_SquaredDifferenceOptions:
+ {
+ auto ptr = reinterpret_cast<circle::SquaredDifferenceOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_MirrorPadOptions:
+ {
+ auto ptr = reinterpret_cast<circle::MirrorPadOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_AbsOptions:
+ {
+ auto ptr = reinterpret_cast<circle::AbsOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_SplitVOptions:
+ {
+ auto ptr = reinterpret_cast<circle::SplitVOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_UniqueOptions:
+ {
+ auto ptr = reinterpret_cast<circle::UniqueOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_ReverseV2Options:
+ {
+ auto ptr = reinterpret_cast<circle::ReverseV2OptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_AddNOptions:
+ {
+ auto ptr = reinterpret_cast<circle::AddNOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_GatherNdOptions:
+ {
+ auto ptr = reinterpret_cast<circle::GatherNdOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_CosOptions:
+ {
+ auto ptr = reinterpret_cast<circle::CosOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_WhereOptions:
+ {
+ auto ptr = reinterpret_cast<circle::WhereOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_RankOptions:
+ {
+ auto ptr = reinterpret_cast<circle::RankOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_ReverseSequenceOptions:
+ {
+ auto ptr = reinterpret_cast<circle::ReverseSequenceOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_MatrixDiagOptions:
+ {
+ auto ptr = reinterpret_cast<circle::MatrixDiagOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_QuantizeOptions:
+ {
+ auto ptr = reinterpret_cast<circle::QuantizeOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_MatrixSetDiagOptions:
+ {
+ auto ptr = reinterpret_cast<circle::MatrixSetDiagOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_HardSwishOptions:
+ {
+ auto ptr = reinterpret_cast<circle::HardSwishOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_IfOptions:
+ {
+ auto ptr = reinterpret_cast<circle::IfOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_WhileOptions:
+ {
+ auto ptr = reinterpret_cast<circle::WhileOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_DepthToSpaceOptions:
+ {
+ auto ptr = reinterpret_cast<circle::DepthToSpaceOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_NonMaxSuppressionV4Options:
+ {
+ auto ptr = reinterpret_cast<circle::NonMaxSuppressionV4OptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_NonMaxSuppressionV5Options:
+ {
+ auto ptr = reinterpret_cast<circle::NonMaxSuppressionV5OptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_ScatterNdOptions:
+ {
+ auto ptr = reinterpret_cast<circle::ScatterNdOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_SelectV2Options:
+ {
+ auto ptr = reinterpret_cast<circle::SelectV2OptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_DensifyOptions:
+ {
+ auto ptr = reinterpret_cast<circle::DensifyOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_SegmentSumOptions:
+ {
+ auto ptr = reinterpret_cast<circle::SegmentSumOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_BatchMatMulOptions:
+ {
+ auto ptr = reinterpret_cast<circle::BatchMatMulOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_CumsumOptions:
+ {
+ auto ptr = reinterpret_cast<circle::CumsumOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_CallOnceOptions:
+ {
+ auto ptr = reinterpret_cast<circle::CallOnceOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_BroadcastToOptions:
+ {
+ auto ptr = reinterpret_cast<circle::BroadcastToOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_Rfft2dOptions:
+ {
+ auto ptr = reinterpret_cast<circle::Rfft2dOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_Conv3DOptions:
+ {
+ auto ptr = reinterpret_cast<circle::Conv3DOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_HashtableOptions:
+ {
+ auto ptr = reinterpret_cast<circle::HashtableOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_HashtableFindOptions:
+ {
+ auto ptr = reinterpret_cast<circle::HashtableFindOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_HashtableImportOptions:
+ {
+ auto ptr = reinterpret_cast<circle::HashtableImportOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_HashtableSizeOptions:
+ {
+ auto ptr = reinterpret_cast<circle::HashtableSizeOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_VarHandleOptions:
+ {
+ auto ptr = reinterpret_cast<circle::VarHandleOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_ReadVariableOptions:
+ {
+ auto ptr = reinterpret_cast<circle::ReadVariableOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_AssignVariableOptions:
+ {
+ auto ptr = reinterpret_cast<circle::AssignVariableOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_RandomOptions:
+ {
+ auto ptr = reinterpret_cast<circle::RandomOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_BCQGatherOptions:
+ {
+ auto ptr = reinterpret_cast<circle::BCQGatherOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_BCQFullyConnectedOptions:
+ {
+ auto ptr = reinterpret_cast<circle::BCQFullyConnectedOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ case BuiltinOptions_InstanceNormOptions:
+ {
+ auto ptr = reinterpret_cast<circle::InstanceNormOptionsT *>(value);
+ delete ptr;
+ break;
+ }
+ default:
+ break;
+ }
+ value = nullptr;
+ type = BuiltinOptions_NONE;
+}
+
+inline const circle::Model *GetModel(const void *buf)
+{
+ return flatbuffers::GetRoot<circle::Model>(buf);
+}
+
+inline const circle::Model *GetSizePrefixedModel(const void *buf)
+{
+ return flatbuffers::GetSizePrefixedRoot<circle::Model>(buf);
+}
+
+inline const char *ModelIdentifier() { return "CIR0"; }
+
+inline bool ModelBufferHasIdentifier(const void *buf)
+{
+ return flatbuffers::BufferHasIdentifier(buf, ModelIdentifier());
+}
+
+inline bool VerifyModelBuffer(flatbuffers::Verifier &verifier)
+{
+ return verifier.VerifyBuffer<circle::Model>(ModelIdentifier());
+}
+
+inline bool VerifySizePrefixedModelBuffer(flatbuffers::Verifier &verifier)
+{
+ return verifier.VerifySizePrefixedBuffer<circle::Model>(ModelIdentifier());
+}
+
+inline const char *ModelExtension() { return "circle"; }
+
+inline void FinishModelBuffer(flatbuffers::FlatBufferBuilder &fbb,
+ flatbuffers::Offset<circle::Model> root)
+{
+ fbb.Finish(root, ModelIdentifier());
+}
+
+inline void FinishSizePrefixedModelBuffer(flatbuffers::FlatBufferBuilder &fbb,
+ flatbuffers::Offset<circle::Model> root)
+{
+ fbb.FinishSizePrefixed(root, ModelIdentifier());
+}
+
+inline std::unique_ptr<circle::ModelT>
+UnPackModel(const void *buf, const flatbuffers::resolver_function_t *res = nullptr)
+{
+ return std::unique_ptr<circle::ModelT>(GetModel(buf)->UnPack(res));
+}
+
+inline std::unique_ptr<circle::ModelT>
+UnPackSizePrefixedModel(const void *buf, const flatbuffers::resolver_function_t *res = nullptr)
+{
+ return std::unique_ptr<circle::ModelT>(GetSizePrefixedModel(buf)->UnPack(res));
+}
+
+} // namespace circle
+
+#endif // FLATBUFFERS_GENERATED_SCHEMA_CIRCLE_H_
diff --git a/onert-micro/helpers/GenerateKernelsListHelper.cpp b/onert-micro/helpers/GenerateKernelsListHelper.cpp
index 142002036..68b194f39 100644
--- a/onert-micro/helpers/GenerateKernelsListHelper.cpp
+++ b/onert-micro/helpers/GenerateKernelsListHelper.cpp
@@ -88,6 +88,8 @@ std::string get_register_kernel_str(const circle::BuiltinOperator builtin_operat
return "REGISTER_KERNEL(LOGICAL_OR, LogicalOr)";
case circle::BuiltinOperator_LOGISTIC:
return "REGISTER_KERNEL(LOGISTIC, Logistic)";
+ case circle::BuiltinOperator_GATHER:
+ return "REGISTER_KERNEL(GATHER, Gather)";
case circle::BuiltinOperator_MAXIMUM:
return "REGISTER_KERNEL(MAXIMUM, Maximum)";
case circle::BuiltinOperator_MAX_POOL_2D:
@@ -106,10 +108,14 @@ std::string get_register_kernel_str(const circle::BuiltinOperator builtin_operat
return "REGISTER_KERNEL(PAD, Pad)";
case circle::BuiltinOperator_PADV2:
return "REGISTER_KERNEL(PADV2, PadV2)";
+ case circle::BuiltinOperator_PACK:
+ return "REGISTER_KERNEL(PACK, Pack)";
case circle::BuiltinOperator_PRELU:
return "REGISTER_KERNEL(PRELU, PRelu)";
case circle::BuiltinOperator_QUANTIZE:
return "REGISTER_KERNEL(QUANTIZE, Quantize)";
+ case circle::BuiltinOperator_REDUCE_PROD:
+ return "REGISTER_KERNEL(REDUCE_PROD, ReduceCommon)";
case circle::BuiltinOperator_RESHAPE:
return "REGISTER_KERNEL(RESHAPE, Reshape)";
case circle::BuiltinOperator_RESIZE_BILINEAR:
@@ -126,6 +132,8 @@ std::string get_register_kernel_str(const circle::BuiltinOperator builtin_operat
return "REGISTER_KERNEL(SPACE_TO_BATCH_ND, SpaceToBatchND)";
case circle::BuiltinOperator_SPACE_TO_DEPTH:
return "REGISTER_KERNEL(SPACE_TO_DEPTH, SpaceToDepth)";
+ case circle::BuiltinOperator_SLICE:
+ return "REGISTER_KERNEL(SLICE, Slice)";
case circle::BuiltinOperator_STRIDED_SLICE:
return "REGISTER_KERNEL(STRIDED_SLICE, StridedSlice)";
case circle::BuiltinOperator_SQRT:
@@ -140,6 +148,10 @@ std::string get_register_kernel_str(const circle::BuiltinOperator builtin_operat
return "REGISTER_KERNEL(SUB, Sub)";
case circle::BuiltinOperator_SVDF:
return "REGISTER_KERNEL(SVDF, SVDF)";
+ case circle::BuiltinOperator_SPLIT:
+ return "REGISTER_KERNEL(SPLIT, Split)";
+ case circle::BuiltinOperator_SPLIT_V:
+ return "REGISTER_KERNEL(SPLIT_V, SplitV)";
case circle::BuiltinOperator_TANH:
return "REGISTER_KERNEL(TANH, Tanh)";
case circle::BuiltinOperator_TRANSPOSE:
@@ -148,6 +160,8 @@ std::string get_register_kernel_str(const circle::BuiltinOperator builtin_operat
return "REGISTER_KERNEL(TRANSPOSE_CONV, TransposeConv)";
case circle::BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_LSTM:
return "REGISTER_KERNEL(UNIDIRECTIONAL_SEQUENCE_LSTM, UnidirectionalSequenceLSTM)";
+ case circle::BuiltinOperator_WHILE:
+ return "REGISTER_KERNEL(WHILE, While)";
default:
assert(false && "Not supported kernel");
}
diff --git a/onert-micro/luci-interpreter/CMakeLists.txt b/onert-micro/luci-interpreter/CMakeLists.txt
index b07ded2af..1bdfa493f 100644
--- a/onert-micro/luci-interpreter/CMakeLists.txt
+++ b/onert-micro/luci-interpreter/CMakeLists.txt
@@ -1,5 +1,6 @@
set(LUCI_INTERPRETER_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include")
set(LUCI_INTERPRETER_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src")
+set(LUCI_INTERPRETER_PAL_COMMON_DIR "${CMAKE_CURRENT_SOURCE_DIR}/pal/common")
if (NOT LUCI_INTERPRETER_PAL_DIR)
set(LUCI_INTERPRETER_PAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/pal/mcu")
endif()
@@ -26,4 +27,11 @@ endif()
add_compile_options(-fno-exceptions)
add_compile_options(-Os)
+
+# AFAIK, this will enable leak sanitizer, too
+if(ENABLE_SANITIZER)
+ add_compile_options(-fsanitize=address)
+ add_link_options(-fsanitize=address)
+endif(ENABLE_SANITIZER)
+
add_subdirectory(src)
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/Interpreter.h b/onert-micro/luci-interpreter/include/luci_interpreter/Interpreter.h
index 483c78938..0d294753d 100644
--- a/onert-micro/luci-interpreter/include/luci_interpreter/Interpreter.h
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/Interpreter.h
@@ -36,7 +36,7 @@ class Interpreter
{
public:
// Construct default interpreter with dynamic allocations and with input allocations
- explicit Interpreter(const char *model_data_raw);
+ explicit Interpreter(const char *model_data_raw, bool dealloc_input);
#ifdef USE_STATIC_ALLOC
// Construct interpreter with configurations
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/TrainingSettings.h b/onert-micro/luci-interpreter/include/luci_interpreter/TrainingSettings.h
new file mode 100644
index 000000000..40eae7ea5
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/TrainingSettings.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef ENABLE_TRAINING
+
+#ifndef LUCI_INTERPRETER_TRAINING_SETTINGS_H
+#define LUCI_INTERPRETER_TRAINING_SETTINGS_H
+
+#include <stdint.h>
+
+namespace luci_interpreter
+{
+
+namespace training
+{
+
+enum Status
+{
+ Ok,
+ Error,
+ EnableTrainModeError,
+ DoubleTrainModeError
+};
+
+enum MetricsTypeEnum
+{
+ MSE,
+ MAE
+};
+
+enum LossTypeEnum
+{
+ MSE_Loss
+};
+
+enum OptimizerTypeEnum
+{
+ SGD
+};
+
+struct TrainingSettings
+{
+ MetricsTypeEnum metric = MSE;
+ LossTypeEnum error_type = MSE_Loss;
+ OptimizerTypeEnum optimizer_type = SGD;
+ uint32_t number_of_epochs = 1;
+ uint32_t batch_size = 1;
+ float learning_rate = 0.00001;
+ uint32_t number_of_last_trainable_layers = 1;
+};
+
+} // namespace training
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TRAINING_SETTINGS_H
+
+#endif // ENABLE_TRAINING
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/core/Tensor.h b/onert-micro/luci-interpreter/include/luci_interpreter/core/Tensor.h
index 318ec0e41..37c9ed9b4 100644
--- a/onert-micro/luci-interpreter/include/luci_interpreter/core/Tensor.h
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/core/Tensor.h
@@ -30,6 +30,106 @@
namespace luci_interpreter
{
+static constexpr int kMaxSmallSize = 5;
+
+class RuntimeShape
+{
+public:
+ RuntimeShape(const RuntimeShape &other) : _size(other.dimensionsCount())
+ {
+ std::memcpy(dimsData(), other.dimsData(), sizeof(int32_t) * _size);
+ }
+
+ // Returns the total count of elements, that is the size when flattened into a
+ // vector.
+ inline int flatSize() const
+ {
+ int buffer_size = 1;
+ const int *dims_data = reinterpret_cast<const int *>(dimsData());
+ for (int i = 0; i < _size; i++)
+ {
+ buffer_size *= dims_data[i];
+ }
+ return buffer_size;
+ }
+
+ inline int32_t *dimsData() { return _dims; }
+ inline const int32_t *dimsData() const { return _dims; }
+
+ RuntimeShape() : _size(0) {}
+
+ explicit RuntimeShape(int dimensions_count) : _size(dimensions_count)
+ {
+ assert(dimensions_count <= kMaxSmallSize);
+ assert(dimensions_count >= 0);
+ }
+
+ RuntimeShape(int dimensions_count, const int32_t *dims_data) : _size(0)
+ {
+ resize(dimensions_count);
+ int32_t *dst_dims = dimsData();
+ std::memcpy(dst_dims, dims_data, dimensions_count * sizeof(int32_t));
+ }
+
+ RuntimeShape(int new_shape_size, const RuntimeShape &shape, int pad_value) : _size(0)
+ {
+ resize(new_shape_size);
+ const int size_increase = new_shape_size - shape.dimensionsCount();
+ for (int i = 0; i < size_increase; ++i)
+ {
+ setDim(i, pad_value);
+ }
+ std::memcpy(dimsData() + size_increase, shape.dimsData(),
+ sizeof(int32_t) * shape.dimensionsCount());
+ }
+
+ RuntimeShape(int shape_size, int32_t value) : _size(0)
+ {
+ resize(shape_size);
+ for (int i = 0; i < shape_size; ++i)
+ {
+ setDim(i, value);
+ }
+ }
+
+ inline static RuntimeShape extendedShape(int new_shape_size, const RuntimeShape &shape)
+ {
+ return RuntimeShape(new_shape_size, shape, 1);
+ }
+
+ bool operator==(const RuntimeShape &comp) const
+ {
+ return this->_size == comp._size &&
+ std::memcmp(dimsData(), comp.dimsData(), _size * sizeof(int32_t)) == 0;
+ }
+
+ inline int32_t dimensionsCount() const { return _size; }
+
+ inline int32_t dims(int i) const
+ {
+ assert(i <= _size);
+ assert(i >= 0);
+ return _dims[i];
+ }
+ inline void setDim(int i, int32_t val)
+ {
+ assert(i <= _size);
+ assert(i >= 0);
+ _dims[i] = val;
+ }
+
+ inline void resize(int dimensions_count)
+ {
+ assert(dimensions_count <= kMaxSmallSize);
+ assert(dimensions_count >= 0);
+ _size = dimensions_count;
+ }
+
+private:
+ int32_t _size;
+ int32_t _dims[kMaxSmallSize];
+};
+
class Tensor
{
public:
@@ -99,15 +199,26 @@ public:
}
#endif
+ static bool is_constant_tensor(const luci_interpreter::CircleReader *reader,
+ const circle::Tensor *circle_tensor)
+ {
+ return reader->buffers()[circle_tensor->buffer()]->data() != nullptr;
+ }
+
static DataType element_type(const circle::Tensor *circle_tensor)
{
return luci_datatype(circle_tensor->type());
}
+ static VectorWrapper<int32_t> tensor_shape(const circle::Tensor *circle_tensor)
+ {
+ return wrap(circle_tensor->shape());
+ }
+
static int num_dims(const circle::Tensor *circle_tensor)
{
// TODO check removing of wrap
- auto const &const_dims = wrap(circle_tensor->shape());
+ auto const const_dims = wrap(circle_tensor->shape());
return const_dims.size();
}
@@ -115,7 +226,7 @@ public:
{
// TODO check removing of wrap
assert(i >= 0);
- auto const &const_dims = wrap(circle_tensor->shape());
+ auto const const_dims = wrap(circle_tensor->shape());
assert(i < const_dims.size());
return const_dims[i];
@@ -124,7 +235,7 @@ public:
static int32_t num_elements(const circle::Tensor *circle_tensor)
{
int32_t result = 1;
- auto const &const_dims = wrap(circle_tensor->shape());
+ auto const const_dims = wrap(circle_tensor->shape());
for (const int32_t dim : const_dims)
{
result *= dim;
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/core/reader/CircleMicroReader.h b/onert-micro/luci-interpreter/include/luci_interpreter/core/reader/CircleMicroReader.h
index 3967e4067..14021fc9d 100644
--- a/onert-micro/luci-interpreter/include/luci_interpreter/core/reader/CircleMicroReader.h
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/core/reader/CircleMicroReader.h
@@ -179,10 +179,12 @@ public: // direct API
public:
bool parse(const circle::Model *model);
bool select_subgraph(uint32_t subgraph);
+ uint32_t get_current_subgraph_index() const { return _current_subgraph_index; }
private:
const circle::Model *_model{nullptr};
const circle::SubGraph *_current_subgraph{nullptr};
+ uint32_t _current_subgraph_index{0};
};
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/onert-micro-version.h b/onert-micro/luci-interpreter/include/luci_interpreter/onert-micro-version.h
new file mode 100644
index 000000000..5a3839693
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/onert-micro-version.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_MICRO_VERSION_H__
+#define __ONERT_MICRO_VERSION_H__
+
+/**
+ * ONERT_MICRO_VERSION is a uint32 value representing onert-micro version
+ * in 0xMMmmmmPP, where MM = major, mmmm = minor, PP = patch
+ */
+#define ONERT_MICRO_VERSION 0x01000000
+
+#endif // __ONERT_MICRO_VERSION_H__
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/TestDataBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/TestDataBase.h
new file mode 100644
index 000000000..9cd21485c
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/TestDataBase.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_TEST_DATA_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_TEST_DATA_BASE_H
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T, typename U = T> class TestDataBase
+{
+public:
+ virtual ~TestDataBase() = default;
+
+ virtual const unsigned char *get_model_ptr() = 0;
+
+ virtual const std::vector<T> &get_input_data_by_index(int i) = 0;
+ virtual const std::vector<U> &get_output_data_by_index(int i) = 0;
+};
+
+class NegTestDataBase
+{
+public:
+ virtual ~NegTestDataBase() = default;
+ virtual const unsigned char *get_model_ptr() = 0;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_TEST_DATA_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/abs/FloatAbsKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/abs/FloatAbsKernel.h
new file mode 100644
index 000000000..a7e8ccc79
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/abs/FloatAbsKernel.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_FLOAT_ABS_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_ABS_KERNEL_H
+
+#include "TestDataAbsBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace abs_float
+{
+/*
+ * Abs Kernel:
+ *
+ * Input(1, 3, 3, 2)
+ * |
+ * Abs
+ * |
+ * Output(1, 3, 3, 2)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff,
+ 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4e, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {4.5279765, -6.575015, -10.009525, 3.1054533, -0.49870253,
+ -9.601274, 8.061923, 8.651763, 5.580226, -22.497627,
+ -5.331085, -0.5524021, -11.368782, -0.61816937, 11.072669,
+ -10.092069, 7.357945, 8.606385};
+
+const std::vector<float> reference_output_data = {
+ 4.5279765, 6.575015, 10.009525, 3.1054533, 0.49870253, 9.601274, 8.061923, 8.651763, 5.580226,
+ 22.497627, 5.331085, 0.5524021, 11.368782, 0.61816937, 11.072669, 10.092069, 7.357945, 8.606385};
+
+} // namespace abs_float
+
+class TestDataFloatAbs : public TestDataAbsBase<float>
+{
+public:
+ TestDataFloatAbs()
+ {
+ _input_data = abs_float::input_data;
+ _reference_output_data = abs_float::reference_output_data;
+ _test_kernel_model_circle = abs_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatAbs() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_ABS_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/abs/NegAbsKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/abs/NegAbsKernel.h
new file mode 100644
index 000000000..aaf167f56
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/abs/NegAbsKernel.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_ABS_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_ABS_KERNEL_H
+
+#include "TestDataAbsBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_abs_input_output_type_mismatch
+{
+/*
+ * Abs Kernel with input output type mismatch (should be equal):
+ *
+ * Input(1, 3, 3, 2) - Float
+ * |
+ * Abs
+ * |
+ * Output(1, 3, 3, 2) - Int
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff,
+ 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4e, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+} // namespace neg_abs_input_output_type_mismatch
+
+namespace neg_abs_input_output_shape_mismatch
+{
+/*
+ * Abs Kernel with input output type mismatch (should be equal):
+ *
+ * Input(1, 3, 3, 2) - Float
+ * |
+ * Abs
+ * |
+ * Output(3, 3, 2) - Float
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x3c, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff,
+ 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4e, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xd8, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x65, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_abs_input_output_shape_mismatch
+
+class NegTestDataInputOutputTypeMismatchAbsKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInputOutputTypeMismatchAbsKernel()
+ {
+ _test_kernel_model_circle = neg_abs_input_output_type_mismatch::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInputOutputTypeMismatchAbsKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInputOutputShapeMismatchAbsKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInputOutputShapeMismatchAbsKernel()
+ {
+ _test_kernel_model_circle = neg_abs_input_output_shape_mismatch::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInputOutputShapeMismatchAbsKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_ABS_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/abs/TestDataAbsBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/abs/TestDataAbsBase.h
new file mode 100644
index 000000000..1d7fa584b
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/abs/TestDataAbsBase.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_ABS_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_ABS_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataAbsBase : public TestDataBase<T>
+{
+public:
+ TestDataAbsBase() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_ABS_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/add/FloatAddKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/add/FloatAddKernel.h
new file mode 100644
index 000000000..5f9e7429c
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/add/FloatAddKernel.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_ADD_KERNEL_FLOAT_H
+#define LUCI_INTERPRETER_TEST_MODELS_ADD_KERNEL_FLOAT_H
+
+#include "TestDataAddBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace add_float_with_broadcasting
+{
+
+/*
+ * Add Kernel:
+ *
+ * Input_1(2, 5) Input_2(2, 1)
+ * \ /
+ * Add(with broadcast)
+ * |
+ * Output(2, 5)
+ */
+
+const unsigned char test_add_kernel_float_with_broadcasting_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0xc0, 0x00, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x14, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xac, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x31, 0x2e, 0x35, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0xfe, 0xff, 0xff, 0xa0, 0xfe, 0xff, 0xff, 0xa4, 0xfe, 0xff, 0xff, 0xa8, 0xfe, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x64, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00,
+ 0x41, 0x64, 0x64, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0xc6, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x90, 0xff, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63,
+ 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f, 0x31, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x10, 0x00,
+ 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xd8, 0xff, 0xff, 0xff,
+ 0x0b, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input1_data = {11.547888, 16.922003, 23.412094, 7.1120033, -1.9457912,
+ 26.603596, -13.668177, 16.682764, 21.436306, 11.578255};
+const std::vector<float> input2_data = {-18.080006, 4.956518};
+const std::vector<float> reference_output_data = {-6.532118, -1.1580029, 5.3320885, -10.968002,
+ -20.025797, 31.560114, -8.7116585, 21.639282,
+ 26.392824, 16.534773};
+} // namespace add_float_with_broadcasting
+
+namespace add_float_no_broadcasting
+{
+/*
+ * Add Kernel:
+ *
+ * Input_1(2, 5) Input_2(2, 5)
+ * \ /
+ * Add(no broadcast)
+ * |
+ * Output(2, 5)
+ */
+const unsigned char test_add_kernel_float_no_broadcasting_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0xc0, 0x00, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x14, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xac, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x31, 0x2e, 0x35, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x9c, 0xfe, 0xff, 0xff, 0xa0, 0xfe, 0xff, 0xff, 0xa4, 0xfe, 0xff, 0xff, 0xa8, 0xfe, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x64, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00,
+ 0x41, 0x64, 0x64, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0xc6, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x90, 0xff, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63,
+ 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f, 0x31, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x10, 0x00,
+ 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xd8, 0xff, 0xff, 0xff,
+ 0x0b, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+std::vector<float> input1_data = {-18.994303, -21.966125, 13.298149, 14.595678, 14.874681,
+ -7.8676147, 18.542614, 12.96068, 17.352306, 1.6868477};
+std::vector<float> input2_data = {13.860439, 7.7335033, 8.465873, 6.483177, 12.05286,
+ -14.429752, 47.21386, -14.103956, 23.698446, 28.710766};
+std::vector<float> reference_output_data = {-5.1338634, -14.232622, 21.764023, 21.078856,
+ 26.927542, -22.297367, 65.75647, -1.1432762,
+ 41.05075, 30.397614};
+} // namespace add_float_no_broadcasting
+
+class TestDataFloatAdd : public TestDataAddBase<float>
+{
+public:
+ explicit TestDataFloatAdd(bool is_with_broadcast) : TestDataAddBase<float>(is_with_broadcast)
+ {
+ if (is_with_broadcast)
+ {
+ _input1_data = add_float_with_broadcasting::input1_data;
+ _input2_data = add_float_with_broadcasting::input2_data;
+ _reference_output_data = add_float_with_broadcasting::reference_output_data;
+ _test_add_kernel_model_circle =
+ add_float_with_broadcasting::test_add_kernel_float_with_broadcasting_model_circle;
+ }
+ else
+ {
+ _input1_data = add_float_no_broadcasting::input1_data;
+ _input2_data = add_float_no_broadcasting::input2_data;
+ _reference_output_data = add_float_no_broadcasting::reference_output_data;
+ _test_add_kernel_model_circle =
+ add_float_no_broadcasting::test_add_kernel_float_no_broadcasting_model_circle;
+ }
+ }
+
+ ~TestDataFloatAdd() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_ADD_KERNEL_FLOAT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/add/IntAddKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/add/IntAddKernel.h
new file mode 100644
index 000000000..6bc73ff1b
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/add/IntAddKernel.h
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_ADD_KERNEL_INT_H
+#define LUCI_INTERPRETER_TEST_MODELS_ADD_KERNEL_INT_H
+
+#include "TestDataAddBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace add_int_with_broadcasting
+{
+
+/*
+ * Add Kernel:
+ *
+ * Input_1(2, 5) Input_2(2, 1)
+ * \ /
+ * Add(with broadcast)
+ * |
+ * Output(2, 5)
+ */
+const unsigned char test_add_kernel_int32_with_broadcasting_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0xc0, 0x00, 0x00, 0x00, 0x14, 0x02, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xac, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x31, 0x2e, 0x35, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x90, 0xfe, 0xff, 0xff, 0x94, 0xfe, 0xff, 0xff, 0x98, 0xfe, 0xff, 0xff, 0x9c, 0xfe, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x5c, 0xff, 0xff, 0xff,
+ 0x03, 0x00, 0x00, 0x00, 0x41, 0x64, 0x64, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0xc2, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff,
+ 0x0d, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f,
+ 0x31, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00, 0xd8, 0xff, 0xff, 0xff, 0x0b, 0x00, 0x00, 0x00,
+ 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const unsigned char test_add_kernel_int64_with_broadcasting_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0xc0, 0x00, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xac, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x32, 0x2e, 0x36, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xb8, 0xfe, 0xff, 0xff, 0xbc, 0xfe, 0xff, 0xff, 0xc0, 0xfe, 0xff, 0xff, 0xc4, 0xfe, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x84, 0xff, 0xff, 0xff,
+ 0x03, 0x00, 0x00, 0x00, 0x41, 0x64, 0x64, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0xc2, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x1c, 0x00, 0x00, 0x00, 0xb4, 0xff, 0xff, 0xff,
+ 0x0d, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f,
+ 0x31, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<int64_t> input1_data = {-5, 5, 5, 5, -13, -5, -3, 21, 5, -4};
+const std::vector<int64_t> input2_data = {6, -14};
+const std::vector<int64_t> reference_output_data = {1, 11, 11, 11, -7, -19, -17, 7, -9, -18};
+
+const std::vector<int32_t> input1_data_32 = {-5, 5, 5, 5, -13, -5, -3, 21, 5, -4};
+const std::vector<int32_t> input2_data_32 = {6, -14};
+const std::vector<int32_t> reference_output_data_32 = {1, 11, 11, 11, -7, -19, -17, 7, -9, -18};
+} // namespace add_int_with_broadcasting
+
+namespace add_int_no_broadcasting
+{
+/*
+ * Add Kernel:
+ *
+ * Input_1(2, 5) Input_2(2, 5)
+ * \ /
+ * Add(no broadcast)
+ * |
+ * Output(2, 5)
+ */
+const unsigned char test_add_kernel_int32_no_broadcasting_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0xc0, 0x00, 0x00, 0x00, 0x14, 0x02, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xac, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x31, 0x2e, 0x35, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x90, 0xfe, 0xff, 0xff, 0x94, 0xfe, 0xff, 0xff, 0x98, 0xfe, 0xff, 0xff, 0x9c, 0xfe, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x5c, 0xff, 0xff, 0xff,
+ 0x03, 0x00, 0x00, 0x00, 0x41, 0x64, 0x64, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0xc2, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff,
+ 0x0d, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f,
+ 0x31, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00, 0xd8, 0xff, 0xff, 0xff, 0x0b, 0x00, 0x00, 0x00,
+ 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const unsigned char test_add_kernel_int64_no_broadcasting_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0xc0, 0x00, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xac, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x32, 0x2e, 0x36, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xb8, 0xfe, 0xff, 0xff, 0xbc, 0xfe, 0xff, 0xff, 0xc0, 0xfe, 0xff, 0xff, 0xc4, 0xfe, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x84, 0xff, 0xff, 0xff,
+ 0x03, 0x00, 0x00, 0x00, 0x41, 0x64, 0x64, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0xc2, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x1c, 0x00, 0x00, 0x00, 0xb4, 0xff, 0xff, 0xff,
+ 0x0d, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f,
+ 0x31, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+std::vector<int64_t> input1_data = {5, -5, -3, 15, 15, -11, 13, 6, 15, 15};
+std::vector<int64_t> input2_data = {15, 5, 5, 15, 7, 4, 13, 5, 6, 13};
+std::vector<int64_t> reference_output_data = {20, 0, 2, 30, 22, -7, 26, 11, 21, 28};
+
+std::vector<int32_t> input1_data_32 = {5, -5, -3, 15, 15, -11, 13, 6, 15, 15};
+std::vector<int32_t> input2_data_32 = {15, 5, 5, 15, 7, 4, 13, 5, 6, 13};
+std::vector<int32_t> reference_output_data_32 = {20, 0, 2, 30, 22, -7, 26, 11, 21, 28};
+
+} // namespace add_int_no_broadcasting
+
+class TestData64IntAdd : public TestDataAddBase<int64_t>
+{
+public:
+ explicit TestData64IntAdd(bool is_with_broadcast) : TestDataAddBase<int64_t>(is_with_broadcast)
+ {
+ if (is_with_broadcast)
+ {
+ _input1_data = add_int_with_broadcasting::input1_data;
+ _input2_data = add_int_with_broadcasting::input2_data;
+ _reference_output_data = add_int_with_broadcasting::reference_output_data;
+ _test_add_kernel_model_circle =
+ add_int_with_broadcasting::test_add_kernel_int64_with_broadcasting_model_circle;
+ }
+ else
+ {
+ _input1_data = add_int_no_broadcasting::input1_data;
+ _input2_data = add_int_no_broadcasting::input2_data;
+ _reference_output_data = add_int_no_broadcasting::reference_output_data;
+ _test_add_kernel_model_circle =
+ add_int_no_broadcasting::test_add_kernel_int64_no_broadcasting_model_circle;
+ }
+ }
+
+ ~TestData64IntAdd() override = default;
+};
+
+class TestData32IntAdd : public TestDataAddBase<int32_t>
+{
+public:
+ explicit TestData32IntAdd(bool is_with_broadcast) : TestDataAddBase<int32_t>(is_with_broadcast)
+ {
+ if (is_with_broadcast)
+ {
+ _input1_data = add_int_with_broadcasting::input1_data_32;
+ _input2_data = add_int_with_broadcasting::input2_data_32;
+ _reference_output_data = add_int_with_broadcasting::reference_output_data_32;
+ _test_add_kernel_model_circle =
+ add_int_with_broadcasting::test_add_kernel_int32_with_broadcasting_model_circle;
+ }
+ else
+ {
+ _input1_data = add_int_no_broadcasting::input1_data_32;
+ _input2_data = add_int_no_broadcasting::input2_data_32;
+ _reference_output_data = add_int_no_broadcasting::reference_output_data_32;
+ _test_add_kernel_model_circle =
+ add_int_no_broadcasting::test_add_kernel_int32_no_broadcasting_model_circle;
+ }
+ }
+
+ ~TestData32IntAdd() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_ADD_KERNEL_INT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/add/NegAddKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/add/NegAddKernel.h
new file mode 100644
index 000000000..44af3afca
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/add/NegAddKernel.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_ADD_KERNEl_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_ADD_KERNEL_H
+
+#include "TestDataAddBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_add_input_type_mismatch
+{
+/*
+ * Add Kernel with mismatching input type:
+ *
+ * Input_1(1, 4, 4) - Int32 Input_2(1, 4, 4) - Float32
+ * \ /
+ * Add(no broadcast)
+ * |
+ * Output(1, 4, 4)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x9c, 0xfe, 0xff, 0xff, 0xa0, 0xfe, 0xff, 0xff, 0xa4, 0xfe, 0xff, 0xff, 0xa8, 0xfe, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+} // namespace neg_add_input_type_mismatch
+
+namespace neg_add_no_quant_params
+{
+/*
+ * Add Kernel in int16 type without quant params:
+ *
+ * Input_1(1, 4, 4) - Int16 Input_2(1, 4, 4) - Float16
+ * \ /
+ * Add(no broadcast, no quant params)
+ * |
+ * Output(1, 4, 4) - Int16
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xa0, 0xfe, 0xff, 0xff, 0xa4, 0xfe, 0xff, 0xff, 0xa8, 0xfe, 0xff, 0xff, 0xac, 0xfe, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x9c, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0xcc, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+} // namespace neg_add_no_quant_params
+
+class NegTestDataInputMismatchAddKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInputMismatchAddKernel()
+ {
+ _test_kernel_model_circle = neg_add_input_type_mismatch::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInputMismatchAddKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataNoQuantParamsS16AddKernel : public NegTestDataBase
+{
+public:
+ NegTestDataNoQuantParamsS16AddKernel()
+ {
+ _test_kernel_model_circle = neg_add_no_quant_params::test_kernel_model_circle;
+ }
+
+ ~NegTestDataNoQuantParamsS16AddKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_ADD_KERNEL_U8_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/add/TestDataAddBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/add/TestDataAddBase.h
new file mode 100644
index 000000000..8ffa7fbea
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/add/TestDataAddBase.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_ADD_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_ADD_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataAddBase : public TestDataBase<T>
+{
+public:
+ explicit TestDataAddBase(bool)
+ {
+ // Do nothing
+ }
+
+ TestDataAddBase() = delete;
+
+ const unsigned char *get_model_ptr() override final { return _test_add_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input1_data;
+ case 1:
+ return _input2_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input1_data;
+ std::vector<T> _input2_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_add_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_ADD_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/add_n/FloatAddNKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/add_n/FloatAddNKernel.h
new file mode 100644
index 000000000..95fd9666a
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/add_n/FloatAddNKernel.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_ADD_N_KERNEL_FLOAT_H
+#define LUCI_INTERPRETER_TEST_MODELS_ADD_N_KERNEL_FLOAT_H
+
+#include "TestDataAddNBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace add_n_float
+{
+/*
+ * AddN Kernel:
+ *
+ * Input_1(1, 4, 4, 3) Input_2(1, 4, 4, 3) Input_2(1, 4, 4, 3)
+ * \ | /
+ * AddN
+ * |
+ * Output(1, 4, 4, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xcc, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x84, 0xff, 0xff, 0xff, 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff,
+ 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x52, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x74, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xa0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x33,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x6a, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input1_data = {
+ 6.427741, -5.5336685, -6.2939873, 8.121177, -3.0810785, -10.091913, -2.4849992, 1.774254,
+ 13.800129, -22.152988, 12.696625, 0.2929567, 8.354922, 5.7603703, -5.8994074, -18.484707,
+ 8.926415, 15.341654, 4.8836274, 5.289197, -9.766411, 13.688, -2.9341066, 7.2281685,
+ -7.639269, -19.849337, -10.183603, -3.39605, 7.0884247, -4.100115, -13.114395, 20.1859,
+ 8.514902, -2.8839726, -4.8524947, -7.7189302, 12.958817, 0.7408314, -14.70222, -4.840035,
+ -5.6485643, 9.197558, 4.805386, -5.6769075, -4.0590677, -6.5562315, 7.0200677, -0.99683046};
+const std::vector<float> input2_data = {
+ -4.0646977, 3.8888195, -0.45402065, -2.352005, 4.839372, -16.821068, 6.937857, 6.233658,
+ 16.912395, -7.1494417, 6.260419, -0.9814551, 5.560984, 2.5352159, 3.3039222, -13.475629,
+ 21.22035, -14.078774, 5.582642, 4.1715817, -3.3241076, 1.4076965, -1.1146233, -5.846616,
+ -9.14507, -7.9248514, 3.61239, -4.173052, 1.4289827, 1.0473942, -8.506401, -11.117105,
+ 11.395946, -3.0757384, -13.336702, 1.6729355, 9.1125765, -5.3872676, -17.386013, 1.4701926,
+ -16.397867, 9.311203, -9.718552, -8.854298, 8.296376, 3.8650365, 8.381851, -6.6090994};
+const std::vector<float> input3_data = {
+ 11.190196, 5.642186, -7.297735, 11.227684, -1.727619, 1.9045501, -9.593952, -16.171299,
+ -6.0474806, 3.3553686, 19.021252, -3.9855165, 5.2290893, 8.515632, -8.236364, 12.097031,
+ 7.9482317, 1.4470768, -0.58474195, -2.9820383, 9.381822, 8.335634, 0.9053579, -0.120785415,
+ 7.994109, -7.4182167, 9.492107, 0.7696781, 6.868584, 6.2453837, 1.7782576, 5.5902786,
+ 9.0994215, -8.651535, -0.6730907, 1.4408729, 5.3254695, 4.124748, 8.724231, -6.1463547,
+ 2.751103, -4.8675337, -9.386753, -15.851856, 5.0927544, 0.2861572, -2.6495001, -4.626466};
+const std::vector<float> reference_output_data = {
+ 13.55324, 3.997337, -14.045743, 16.996857, 0.030674577, -25.00843, -5.141094, -8.163387,
+ 24.665043, -25.94706, 37.978294, -4.674015, 19.144997, 16.811218, -10.83185, -19.863304,
+ 38.094997, 2.7099562, 9.881528, 6.4787407, -3.7086973, 23.431332, -3.143372, 1.2607672,
+ -8.790231, -35.192406, 2.9208941, -6.7994237, 15.385992, 3.1926632, -19.842539, 14.659074,
+ 29.01027, -14.611246, -18.862288, -4.6051216, 27.396862, -0.521688, -23.364002, -9.516197,
+ -19.29533, 13.641229, -14.299919, -30.38306, 9.330063, -2.4050379, 12.7524185, -12.232395};
+
+} // namespace add_n_float
+
+class TestDataFloatAddN : public TestDataAddNBase<float>
+{
+public:
+ TestDataFloatAddN()
+ {
+ _input1_data = add_n_float::input1_data;
+ _input2_data = add_n_float::input2_data;
+ _input3_data = add_n_float::input3_data;
+ _reference_output_data = add_n_float::reference_output_data;
+ _test_kernel_model_circle = add_n_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatAddN() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_ADD_N_KERNEL_FLOAT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/add_n/NegAddNKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/add_n/NegAddNKernel.h
new file mode 100644
index 000000000..762edd456
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/add_n/NegAddNKernel.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_ADD_N_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_ADD_N_KERNEL_H
+
+#include "TestDataAddNBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace input_type_mismatch_add_n
+{
+/*
+ * AddN Kernel with input1 type != input2 type:
+ *
+ * Input_1(1, 4, 4, 3)-Float Input_2(1, 4, 4, 3) Input_2(1, 4, 4, 3) - Int32
+ * \ | /
+ * AddN
+ * |
+ * Output(1, 4, 4, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xdc, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x84, 0xff, 0xff, 0xff, 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff,
+ 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x52, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x64, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x90, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x33,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x6a, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+} // namespace input_type_mismatch_add_n
+
+class TestDataInputTypeMismatchAddN : public NegTestDataBase
+{
+public:
+ TestDataInputTypeMismatchAddN()
+ {
+ _test_kernel_model_circle = input_type_mismatch_add_n::test_kernel_model_circle;
+ }
+
+ ~TestDataInputTypeMismatchAddN() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_ADD_N_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/add_n/TestDataAddNBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/add_n/TestDataAddNBase.h
new file mode 100644
index 000000000..6b0784536
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/add_n/TestDataAddNBase.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_ADD_N_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_ADD_N_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataAddNBase : public TestDataBase<T>
+{
+public:
+ TestDataAddNBase() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input1_data;
+ case 1:
+ return _input2_data;
+ case 2:
+ return _input3_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input1_data;
+ std::vector<T> _input2_data;
+ std::vector<T> _input3_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_ADD_N_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/argmax/FloatArgMaxKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/argmax/FloatArgMaxKernel.h
new file mode 100644
index 000000000..9d9be08c3
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/argmax/FloatArgMaxKernel.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_ARG_MAX_KERNEL_FLOAT_H
+#define LUCI_INTERPRETER_TEST_MODELS_ARG_MAX_KERNEL_FLOAT_H
+
+#include "TestDataArgMaxBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace argmax_float
+{
+
+/*
+ * ArgMax Kernel:
+ *
+ * Input_1(4, 5) Input_2(scalar = 1)
+ * \ /
+ * ArgMax
+ * |
+ * Output(4)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x6c, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x28, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xd8, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x61, 0x72, 0x67, 0x6d,
+ 0x61, 0x78, 0x2f, 0x64, 0x69, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input1_data = {
+ 16.19906, 15.062998, 19.666464, -20.029007, -15.745727, 0.014214589, -6.178691,
+ 7.236639, -4.1050725, 15.853367, -4.012241, -11.736127, -0.40098614, -17.605135,
+ -7.4517574, -0.11448864, 13.045483, 7.009659, 5.189774, -6.1986547};
+
+const std::vector<int32_t> reference_output_data = {2, 4, 2, 1};
+
+} // namespace argmax_float
+
+class TestDataFloatArgMax : public TestDataArgMaxBase<float, int32_t>
+{
+public:
+ TestDataFloatArgMax()
+ {
+ _input1_data = argmax_float::input1_data;
+ _reference_output_data = argmax_float::reference_output_data;
+ _test_kernel_model_circle = argmax_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatArgMax() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_ARG_MAX_KERNEL_FLOAT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/argmax/NegArgMaxKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/argmax/NegArgMaxKernel.h
new file mode 100644
index 000000000..9d6aff6c7
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/argmax/NegArgMaxKernel.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_ARG_MAX_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_ARG_MAX_KERNEL_H
+
+#include "TestDataArgMaxBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace wrong_output_type_arg_max
+{
+
+/*
+ * ArgMax Kernel with wrong output type (Float32):
+ *
+ * Input_1(4, 5) Input_2(scalar = 1)
+ * \ /
+ * ArgMax
+ * |
+ * Output(4) - Float32
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x6c, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x28, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x14, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x61, 0x72, 0x67, 0x6d, 0x61, 0x78, 0x2f, 0x64,
+ 0x69, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+} // namespace wrong_output_type_arg_max
+
+class TestDataOutputWrongOutputArgMax : public NegTestDataBase
+{
+public:
+ TestDataOutputWrongOutputArgMax()
+ {
+ _test_kernel_model_circle = wrong_output_type_arg_max::test_kernel_model_circle;
+ }
+
+ ~TestDataOutputWrongOutputArgMax() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_ARG_MAX_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/argmax/TestDataArgMaxBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/argmax/TestDataArgMaxBase.h
new file mode 100644
index 000000000..5100d49c4
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/argmax/TestDataArgMaxBase.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_ARG_MAX_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_ARG_MAX_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T, typename O> class TestDataArgMaxBase : public TestDataBase<T, O>
+{
+public:
+ TestDataArgMaxBase() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input1_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<O> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input1_data;
+ std::vector<O> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_ARG_MAX_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/argmin/FloatArgMinKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/argmin/FloatArgMinKernel.h
new file mode 100644
index 000000000..0b915ae28
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/argmin/FloatArgMinKernel.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_ARG_MIN_KERNEL_FLOAT_H
+#define LUCI_INTERPRETER_TEST_MODELS_ARG_MIN_KERNEL_FLOAT_H
+
+#include "TestDataArgMinBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace argmin_float
+{
+
+/*
+ * ArgMin Kernel:
+ *
+ * Input_1(4, 5) Input_2(scalar = 1)
+ * \ /
+ * ArgMin
+ * |
+ * Output(4)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x6c, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x39, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xd8, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x61, 0x72, 0x67, 0x6d,
+ 0x69, 0x6e, 0x2f, 0x64, 0x69, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input1_data = {
+ 16.19906, 15.062998, 19.666464, -20.029007, -15.745727, 0.014214589, -6.178691,
+ 7.236639, -4.1050725, 15.853367, -4.012241, -11.736127, -0.40098614, -17.605135,
+ -7.4517574, -0.11448864, 13.045483, 7.009659, 5.189774, -6.1986547};
+
+const std::vector<int32_t> reference_output_data = {3, 1, 3, 4};
+
+} // namespace argmin_float
+
+class TestDataFloatArgMin : public TestDataArgMinBase<float, int32_t>
+{
+public:
+ TestDataFloatArgMin()
+ {
+ _input1_data = argmin_float::input1_data;
+ _reference_output_data = argmin_float::reference_output_data;
+ _test_kernel_model_circle = argmin_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatArgMin() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_ARG_MIN_KERNEL_FLOAT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/argmin/NegArgMinKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/argmin/NegArgMinKernel.h
new file mode 100644
index 000000000..0eaeb66b8
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/argmin/NegArgMinKernel.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_ARG_MIN_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_ARG_MIN_KERNEL_H
+
+#include "TestDataArgMinBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace wrong_output_type_arg_min
+{
+
+/*
+ * ArgMin Kernel with wrong output type (Float32):
+ *
+ * Input_1(4, 5) Input_2(scalar = 1)
+ * \ /
+ * ArgMin
+ * |
+ * Output(4) - Float32
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff,
+ 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39,
+ 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x3c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x61, 0x72, 0x67, 0x6d,
+ 0x69, 0x6e, 0x2f, 0x64, 0x69, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+} // namespace wrong_output_type_arg_min
+
+class TestDataOutputWrongOutputArgMin : public NegTestDataBase
+{
+public:
+ TestDataOutputWrongOutputArgMin()
+ {
+ _test_kernel_model_circle = wrong_output_type_arg_min::test_kernel_model_circle;
+ }
+
+ ~TestDataOutputWrongOutputArgMin() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_ARG_MIN_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/argmin/TestDataArgMinBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/argmin/TestDataArgMinBase.h
new file mode 100644
index 000000000..8ae22c4e0
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/argmin/TestDataArgMinBase.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_ARG_MIN_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_ARG_MIN_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T, typename O> class TestDataArgMinBase : public TestDataBase<T, O>
+{
+public:
+ TestDataArgMinBase() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input1_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<O> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input1_data;
+ std::vector<O> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_ARG_MIN_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/average_pool_2d/FloatAveragePool2DKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/average_pool_2d/FloatAveragePool2DKernel.h
new file mode 100644
index 000000000..58790e94b
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/average_pool_2d/FloatAveragePool2DKernel.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_FLOAT_AVERAGE_POOL2D_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_AVERAGE_POOL2D_KERNEL_H
+
+#include "TestDataAveragePool2DBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace average_pool2d_float
+{
+/*
+ * AveragePool2D Kernel:
+ *
+ * Input(1, 8, 8, 1)
+ * |
+ * AveragePool2D
+ * |
+ * Output(1, 7, 7, 1)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x48, 0x01, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff,
+ 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x1c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x17, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {
+ -10.829727, -5.0753784, -0.46581638, 1.1337309, -12.983028, -1.7739874, -3.8115792, -1.470794,
+ 0.8652655, 3.5751436, 3.142009, -2.881177, 0.21681504, -0.6201232, -1.168152, -5.972758,
+ 6.4394593, 0.60464424, -1.8141485, -17.769108, -13.40761, 6.139243, -2.3543136, -2.5557704,
+ 15.057343, 7.4924536, -20.035614, 4.250232, 5.9063106, 10.382995, -7.45354, 3.7568998,
+ 5.0376787, 2.825182, -7.3617344, -3.2233214, 2.2610564, -6.776909, -2.56466, 17.584259,
+ 15.771288, 5.9487047, -0.11435696, 8.510494, 9.547339, 11.753286, 12.103353, -14.300014,
+ 4.453389, 11.3001, -7.494295, 9.240987, -2.8403296, -1.9216467, 8.1578245, -7.334697,
+ 1.2287734, 0.7231084, 9.715425, -7.466359, -15.67608, 6.574766, 4.489766, -1.6495954};
+
+const std::vector<float> reference_output_data{
+ -2.866174, 0.29398948, 0.23218668, -3.6284149, -3.790081, -1.8434604, -3.1058207,
+ 2.871128, 1.376912, -4.830606, -8.46027, -1.9179188, 0.4991635, -3.0127485,
+ 7.3984747, -3.4381661, -8.842159, -5.2550435, 2.2552347, 1.678596, -2.151681,
+ 7.6031637, -4.269928, -6.5926094, 2.2985694, 2.9433632, -1.6030285, 2.83074,
+ 7.395714, 0.32444882, -0.54722965, 4.273892, 4.196193, 3.6287675, 3.2057345,
+ 9.368371, 2.4100385, 2.535707, 6.1146226, 4.134662, 7.523204, -0.3433833,
+ 4.426343, 3.5610845, 0.9989393, -4.1854453, -3.4658222, 4.3251777, 0.91582465};
+
+} // namespace average_pool2d_float
+
+class TestDataFloatAveragePool2D : public TestDataAveragePool2DBase<float>
+{
+public:
+ TestDataFloatAveragePool2D()
+ {
+ _input_data = average_pool2d_float::input_data;
+ _reference_output_data = average_pool2d_float::reference_output_data;
+ _test_kernel_model_circle = average_pool2d_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatAveragePool2D() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_AVERAGE_POOL2D_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/average_pool_2d/NegAveragePool2DKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/average_pool_2d/NegAveragePool2DKernel.h
new file mode 100644
index 000000000..0c1c5a29b
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/average_pool_2d/NegAveragePool2DKernel.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_AVERAGE_POOL2D_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_AVERAGE_POOL2D_KERNEL_H
+
+#include "TestDataAveragePool2DBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_average_pool2d_kernel
+{
+/*
+ * AveragePool2D Kernel with input_type != output_type:
+ *
+ * Input(1, 8, 8, 1) = Float32
+ * |
+ * AveragePool2D
+ * |
+ * Output(1, 7, 7, 1) = Int32
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x58, 0x01, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff,
+ 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x1c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x17, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x50, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+} // namespace neg_average_pool2d_kernel
+
+class NegTestDataInputOutputTypeMismatchAveragePool2DKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInputOutputTypeMismatchAveragePool2DKernel()
+ {
+ _test_kernel_model_circle = neg_average_pool2d_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInputOutputTypeMismatchAveragePool2DKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_AVERAGE_POOL2D_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/average_pool_2d/TestDataAveragePool2DBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/average_pool_2d/TestDataAveragePool2DBase.h
new file mode 100644
index 000000000..c7de059cd
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/average_pool_2d/TestDataAveragePool2DBase.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_AVERAGE_POOL_2D_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_AVERAGE_POOL_2D_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataAveragePool2DBase : public TestDataBase<T>
+{
+public:
+ TestDataAveragePool2DBase() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_AVERAGE_POOL_2D_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/concatenation/FloatConcatenationKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/concatenation/FloatConcatenationKernel.h
new file mode 100644
index 000000000..2908bef0c
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/concatenation/FloatConcatenationKernel.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_CONCATENATION_KERNEL_FLOAT_H
+#define LUCI_INTERPRETER_TEST_MODELS_CONCATENATION_KERNEL_FLOAT_H
+
+#include "TestDataConcatenationBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace concatenation_float
+{
+
+/*
+ * Concatenation Kernel:
+ *
+ * Input_1(1, 4, 4, 1) Input_2(1, 4, 4, 2)
+ * \ /
+ * Concatenation
+ * |
+ * Output(1, 4, 4, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xf4, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
+ 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xa4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0xd0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input1_data = {
+ -2.0978436, -25.836285, 7.9663463, -52.951416, -9.174321, -10.963295, 1.4337301, -39.000927,
+ -11.76153, -24.070623, -21.426125, -32.041714, -2.29292, -7.595441, -15.297459, -20.068735};
+const std::vector<float> input2_data = {
+ -23.881905, -8.470397, -52.49611, -21.756306, 1.581161, -26.177217, -39.463478, -2.172443,
+ -30.588694, -7.90017, -17.604687, -27.376356, -26.49272, -15.772057, 8.418157, -36.710365,
+ -35.77088, -27.592611, -5.0617495, -7.8632812, 10.318075, -33.451294, -53.1594, -33.312737,
+ -6.132754, -21.647987, -38.427383, -41.75349, -22.417152, -1.243468, -19.772722, -55.897236};
+const std::vector<float> reference_output_data = {
+ -2.0978436, -23.881905, -8.470397, -25.836285, -52.49611, -21.756306, 7.9663463, 1.581161,
+ -26.177217, -52.951416, -39.463478, -2.172443, -9.174321, -30.588694, -7.90017, -10.963295,
+ -17.604687, -27.376356, 1.4337301, -26.49272, -15.772057, -39.000927, 8.418157, -36.710365,
+ -11.76153, -35.77088, -27.592611, -24.070623, -5.0617495, -7.8632812, -21.426125, 10.318075,
+ -33.451294, -32.041714, -53.1594, -33.312737, -2.29292, -6.132754, -21.647987, -7.595441,
+ -38.427383, -41.75349, -15.297459, -22.417152, -1.243468, -20.068735, -19.772722, -55.897236};
+
+} // namespace concatenation_float
+
+class TestDataFloatConcatenation : public TestDataConcatenationBase<float>
+{
+public:
+ TestDataFloatConcatenation()
+ {
+ _input1_data = concatenation_float::input1_data;
+ _input2_data = concatenation_float::input2_data;
+ _reference_output_data = concatenation_float::reference_output_data;
+ _test_kernel_model_circle = concatenation_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatConcatenation() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_CONCATENATION_KERNEL_FLOAT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/concatenation/IntConcatenationKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/concatenation/IntConcatenationKernel.h
new file mode 100644
index 000000000..fe0b7f511
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/concatenation/IntConcatenationKernel.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_CONCATENATION_KERNEL_INT_H
+#define LUCI_INTERPRETER_TEST_MODELS_CONCATENATION_KERNEL_INT_H
+
+#include "TestDataConcatenationBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace concatenation_int32
+{
+
+/*
+ * Concatenation Kernel:
+ *
+ * Input_1(1, 4, 4, 1) Input_2(1, 4, 4, 2)
+ * \ /
+ * Concatenation
+ * |
+ * Output(1, 4, 4, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xf4, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
+ 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x9c, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0xcc, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<int32_t> input1_data = {-9, -22, -32, 7, -23, -8, -23, -32,
+ -31, -25, -8, -22, -23, 1, -24, -32};
+const std::vector<int32_t> input2_data = {-29, -31, -8, -23, 16, -23, -38, 7, -36, -22, -32,
+ -24, -23, -18, -33, -23, -38, -24, -38, -14, -16, -13,
+ -15, -22, -38, -53, -5, -40, -23, -22, -23, -41};
+const std::vector<int32_t> reference_output_data = {
+ -9, -29, -31, -22, -8, -23, -32, 16, -23, 7, -38, 7, -23, -36, -22, -8,
+ -32, -24, -23, -23, -18, -32, -33, -23, -31, -38, -24, -25, -38, -14, -8, -16,
+ -13, -22, -15, -22, -23, -38, -53, 1, -5, -40, -24, -23, -22, -32, -23, -41};
+
+} // namespace concatenation_int32
+
+namespace concatenation_int64
+{
+
+/*
+ * Concatenation Kernel:
+ *
+ * Input_1(1, 4, 4, 1) Input_2(1, 4, 4, 2)
+ * \ /
+ * Concatenation
+ * |
+ * Output(1, 4, 4, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xf4, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
+ 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x9c, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0xcc, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<int64_t> input1_data = {35, 35, 35, 35, 30, 40, 45, 30,
+ 35, 35, 35, 40, 35, 30, 25, 30};
+const std::vector<int64_t> input2_data = {25, 35, 35, 30, 40, 35, 30, 35, 35, 35, 40,
+ 25, 35, 30, 40, 35, 35, 35, 30, 30, 35, 35,
+ 45, 50, 45, 35, 35, 40, 35, 35, 30, 35};
+const std::vector<int64_t> reference_output_data = {
+ 35, 25, 35, 35, 35, 30, 35, 40, 35, 35, 30, 35, 30, 35, 35, 40, 40, 25, 45, 35, 30, 30, 40, 35,
+ 35, 35, 35, 35, 30, 30, 35, 35, 35, 40, 45, 50, 35, 45, 35, 30, 35, 40, 25, 35, 35, 30, 30, 35};
+
+} // namespace concatenation_int64
+
+class TestDataS32Concatenation : public TestDataConcatenationBase<int32_t>
+{
+public:
+ TestDataS32Concatenation()
+ {
+ _input1_data = concatenation_int32::input1_data;
+ _input2_data = concatenation_int32::input2_data;
+ _reference_output_data = concatenation_int32::reference_output_data;
+ _test_kernel_model_circle = concatenation_int32::test_kernel_model_circle;
+ }
+
+ ~TestDataS32Concatenation() override = default;
+};
+
+class TestDataS64Concatenation : public TestDataConcatenationBase<int64_t>
+{
+public:
+ TestDataS64Concatenation()
+ {
+ _input1_data = concatenation_int64::input1_data;
+ _input2_data = concatenation_int64::input2_data;
+ _reference_output_data = concatenation_int64::reference_output_data;
+ _test_kernel_model_circle = concatenation_int64::test_kernel_model_circle;
+ }
+
+ ~TestDataS64Concatenation() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_CONCATENATION_KERNEL_INT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/concatenation/NegConcatenationKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/concatenation/NegConcatenationKernel.h
new file mode 100644
index 000000000..c2594d5f2
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/concatenation/NegConcatenationKernel.h
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_CONCATENATION_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_CONCATENATION_KERNEL_H
+
+#include "TestDataConcatenationBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace input_type_mismatch_concatenation
+{
+
+/*
+ * Concatenation Kernel with input1 type != input2 type:
+ *
+ * Input_1(1, 4, 4, 1)- Int32 Input_2(1, 4, 4, 2) - Float32
+ * \ /
+ * Concatenation
+ * |
+ * Output(1, 4, 4, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00, 0xa4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xf4, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
+ 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+} // namespace input_type_mismatch_concatenation
+
+namespace concatenation_with_relu
+{
+
+/*
+ * Concatenation Kernel with relu activation:
+ *
+ * Input_1(1, 4, 4, 1)- Float32 Input_2(1, 4, 4, 2) - Float32
+ * \ /
+ * Concatenation(ReLU)
+ * |
+ * Output(1, 4, 4, 3) - Float32
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xf4, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
+ 0x78, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+} // namespace concatenation_with_relu
+
+namespace concatenation_with_wrong_axis
+{
+
+/*
+ * Concatenation Kernel with wrong axis params:
+ *
+ * Input_1(1, 4, 4, 1)- Float32 Input_2(1, 4, 4, 2) - Float32
+ * \ /
+ * Concatenation(axis = 6, should be < 4)
+ * |
+ * Output(1, 4, 4, 3) - Float32
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xf4, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
+ 0x78, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+} // namespace concatenation_with_wrong_axis
+
+class TestDataInputTypeMismatchConcatenation : public NegTestDataBase
+{
+public:
+ TestDataInputTypeMismatchConcatenation()
+ {
+ _test_kernel_model_circle = input_type_mismatch_concatenation::test_kernel_model_circle;
+ }
+
+ ~TestDataInputTypeMismatchConcatenation() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class TestDataReluConcatenation : public NegTestDataBase
+{
+public:
+ TestDataReluConcatenation()
+ {
+ _test_kernel_model_circle = concatenation_with_relu::test_kernel_model_circle;
+ }
+
+ ~TestDataReluConcatenation() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class TestDataWrongAxisConcatenation : public NegTestDataBase
+{
+public:
+ TestDataWrongAxisConcatenation()
+ {
+ _test_kernel_model_circle = concatenation_with_wrong_axis::test_kernel_model_circle;
+ }
+
+ ~TestDataWrongAxisConcatenation() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_CONCATENATION_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/concatenation/TestDataConcatenationBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/concatenation/TestDataConcatenationBase.h
new file mode 100644
index 000000000..5b94eb063
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/concatenation/TestDataConcatenationBase.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_CONCATENATION_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_CONCATENATION_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataConcatenationBase : public TestDataBase<T>
+{
+public:
+ TestDataConcatenationBase() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input1_data;
+ case 1:
+ return _input2_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input1_data;
+ std::vector<T> _input2_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_CONCATENATION_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/conv2d/FloatConv2DKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/conv2d/FloatConv2DKernel.h
new file mode 100644
index 000000000..eef549cbf
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/conv2d/FloatConv2DKernel.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_CONV_2D_KERNEL_FLOAT_H
+#define LUCI_INTERPRETER_TEST_MODELS_CONV_2D_KERNEL_FLOAT_H
+
+#include "TestDataConv2DBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace conv2d_float
+{
+
+/*
+ * Conv2D Kernel:
+ *
+ * Input(1, 4, 3, 2) Weight(1, 2, 2, 2) Bias(2)
+ * \ | /
+ * \ | /
+ * FullyConnected
+ * |
+ * Output(1, 2, 2, 2)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x9c, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x2c, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x88, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xea, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0xc0, 0x00, 0x00, 0x80, 0xc0, 0x00, 0x00, 0xa0, 0xc0,
+ 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0xe0, 0xc0, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x80, 0x40,
+ 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x00, 0xc1,
+ 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0xe0, 0x40, 0x00, 0x00, 0xa0, 0x40, 0xf8, 0xff, 0xff, 0xff,
+ 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x07, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x98, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x84, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xb0, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0xd4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x6b, 0x65, 0x72, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {
+ 18.776451, 25.97969, -9.277071, -3.5493946, 12.334248, 5.50226, -2.224743, -7.2292213,
+ 10.259663, -1.0846977, 15.823856, 3.3193378, 4.9413986, 4.3529205, -10.353054, 3.7166824,
+ 27.324902, -6.2231064, 10.370632, 22.661959, 20.206001, 8.245907, 9.984943, 21.379955};
+
+const std::vector<float> reference_output_data = {1.0177879, 128.43202, 0.0, 55.28556,
+ 39.483513, 0.0, 0.0, 7.0231743};
+
+} // namespace conv2d_float
+
+class TestDataFloatConv2D : public TestDataConv2DBase<float>
+{
+public:
+ TestDataFloatConv2D()
+ {
+ _input_data = conv2d_float::input_data;
+ _reference_output_data = conv2d_float::reference_output_data;
+ _test_kernel_model_circle = conv2d_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatConv2D() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_CONV_2D_KERNEL_FLOAT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/conv2d/NegConv2DKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/conv2d/NegConv2DKernel.h
new file mode 100644
index 000000000..52baf89db
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/conv2d/NegConv2DKernel.h
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_CONV_2D_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_CONV_2D_KERNEL_H
+
+#include "TestDataConv2DBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_conv2d_input_type_mismatch
+{
+
+/*
+ * Conv2D Kernel with input type mismatch (input_type should be equal to weight_type):
+ *
+ * Input(1, 3, 3, 2) - Float32 Weight(1, 1, 1, 2) - Int32 Bias(1)
+ * \ | /
+ * \ | /
+ * Conv2D
+ * |
+ * Output(1, 3, 3, 1)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x4c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xee, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0xfe, 0x4c, 0xbf, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xa8, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x74, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xa0, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x6b, 0x65, 0x72, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_conv2d_input_type_mismatch
+
+namespace neg_conv2d_bias_wrong_type
+{
+/*
+ * Conv2D Kernel with wrong bias type (should be equal to input_type):
+ *
+ * Input(1, 3, 3, 2) - Float32 Weight(1, 1, 1, 2) - Float32 Bias(1) - Int32
+ * \ | /
+ * \ | /
+ * Conv2D
+ * |
+ * Output(1, 3, 3, 1)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x4c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xee, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x98, 0xb5, 0x03, 0xbe, 0x6b, 0x02, 0xeb, 0x3e,
+ 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xa8, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x74, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0xd4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x6b, 0x65, 0x72, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_conv2d_bias_wrong_type
+
+namespace neg_conv2d_invalid_input_shape
+{
+/*
+ * Conv2D Kernel with invalid input shape (rank should be == 4):
+ *
+ * Input(1, 1, 3, 3, 2) - Float32 Weight(1, 1, 1, 2) - Float32 Bias(1) - Int32
+ * \ | /
+ * \ | /
+ * Conv2D
+ * |
+ * Output(1, 1, 3, 3, 1)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x4c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xee, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xcb, 0xe5, 0x9c, 0x3f, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x5b, 0xe7, 0x8c, 0xbf, 0x06, 0xc5, 0x2f, 0x3f,
+ 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x9c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x80, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0xb0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6b, 0x65, 0x72, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_conv2d_invalid_input_shape
+
+class NegTestDataInputMismatchConv2DKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInputMismatchConv2DKernel()
+ {
+ _test_kernel_model_circle = neg_conv2d_input_type_mismatch::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInputMismatchConv2DKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataWrongBiasTypeConv2DKernel : public NegTestDataBase
+{
+public:
+ NegTestDataWrongBiasTypeConv2DKernel()
+ {
+ _test_kernel_model_circle = neg_conv2d_bias_wrong_type::test_kernel_model_circle;
+ }
+
+ ~NegTestDataWrongBiasTypeConv2DKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInvalidInputTypeConv2DKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInvalidInputTypeConv2DKernel()
+ {
+ _test_kernel_model_circle = neg_conv2d_bias_wrong_type::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInvalidInputTypeConv2DKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_CONV_2D_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/conv2d/TestDataConv2DBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/conv2d/TestDataConv2DBase.h
new file mode 100644
index 000000000..ce888ac3a
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/conv2d/TestDataConv2DBase.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_CONV_2D_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_CONV_2D_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataConv2DBase : public TestDataBase<T>
+{
+public:
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_CONV_2D_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/conv2d/U8Conv2DKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/conv2d/U8Conv2DKernel.h
new file mode 100644
index 000000000..dd992be1d
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/conv2d/U8Conv2DKernel.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_CONV_2D_KERNEL_U8_H
+#define LUCI_INTERPRETER_TEST_MODELS_CONV_2D_KERNEL_U8_H
+
+#include "TestDataConv2DBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace conv2d_u8
+{
+
+/*
+ * Conv2D Kernel:
+ *
+ * Input(1, 3, 3, 2) Weight(1, 1, 1, 2) Bias(1)
+ * \ | /
+ * \ | /
+ * FullyConnected
+ * |
+ * Output(1, 3, 3, 1)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x1c, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0xe0, 0x02, 0x00, 0x00, 0xfc, 0x02, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xee, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x65, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x8d, 0x44, 0x00, 0x00,
+ 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x5c, 0x01, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xc2, 0xfe, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x48, 0x00, 0x00, 0x00, 0xb4, 0xfe, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0xa1, 0xa0, 0x20, 0x3d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x32, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x44, 0x00, 0x00, 0x00, 0x24, 0xff, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x87, 0x7b, 0x24, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x92, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x44, 0x00, 0x00, 0x00, 0x84, 0xff, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xa1, 0xa0, 0x20, 0x3d,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0,
+ 0x03, 0x00, 0x00, 0x00, 0x6b, 0x65, 0x72, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x54, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x6f, 0x12, 0x83, 0x3b, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<uint8_t> input_data = {5, 11, 5, 251, 5, 252, 22, 14, 251,
+ 5, 23, 5, 6, 245, 5, 33, 15, 252};
+
+const std::vector<uint8_t> reference_output_data = {103, 70, 70, 105, 142, 106, 71, 100, 71};
+
+} // namespace conv2d_u8
+
+class TestDataU8Conv2D : public TestDataConv2DBase<uint8_t>
+{
+public:
+ TestDataU8Conv2D()
+ {
+ _input_data = conv2d_u8::input_data;
+ _reference_output_data = conv2d_u8::reference_output_data;
+ _test_kernel_model_circle = conv2d_u8::test_kernel_model_circle;
+ }
+
+ ~TestDataU8Conv2D() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_CONV_2D_KERNEL_U8_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/div/FloatDivKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/div/FloatDivKernel.h
new file mode 100644
index 000000000..ed9408a16
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/div/FloatDivKernel.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_DIV_KERNEL_FLOAT_H
+#define LUCI_INTERPRETER_TEST_MODELS_DIV_KERNEL_FLOAT_H
+
+#include "TestDataDivBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace div_float_with_broadcasting
+{
+
+/*
+ * Div Kernel:
+ *
+ * Input_1(2, 5) Input_2(2, 1)
+ * \ /
+ * Div(with broadcast)
+ * |
+ * Output(2, 5)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xb4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xd8, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input1_data = {8.432024, 5.4664106, 16.856224, -10.004156, -14.128681,
+ 12.695552, -7.5779333, -1.1460792, 15.574873, -12.670321};
+const std::vector<float> input2_data = {-2.0361109, -9.528288};
+const std::vector<float> reference_output_data = {-4.14124, -2.6847312, -8.278638, 4.913365,
+ 6.939053, -1.3324064, 0.795309, 0.120281756,
+ -1.634593, 1.3297584};
+
+} // namespace div_float_with_broadcasting
+
+namespace div_float_no_broadcasting
+{
+/*
+ * Div Kernel:
+ *
+ * Input_1(2, 5) Input_2(2, 5)
+ * \ /
+ * Div(no broadcast)
+ * |
+ * Output(2, 5)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xb4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xd8, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+std::vector<float> input1_data = {3.563036, 13.645134, 0.427146, 11.032923, 0.4189046,
+ 15.737275, 7.7726707, 0.75059056, -7.833488, 3.0679407};
+std::vector<float> input2_data = {-0.62832826, 7.937863, -14.899745, 0.2819096, -5.8306913,
+ 8.6010685, -10.391579, -3.312385, -11.495937, 5.5657125};
+std::vector<float> reference_output_data = {-5.67066, 1.7189934, -0.028668007, 39.136383,
+ -0.07184476, 1.8296884, -0.74797785, -0.22660124,
+ 0.6814136, 0.55122155};
+
+} // namespace div_float_no_broadcasting
+
+class TestDataFloatDiv : public TestDataDivBase<float>
+{
+public:
+ explicit TestDataFloatDiv(bool is_with_broadcast) : TestDataDivBase<float>(is_with_broadcast)
+ {
+ if (is_with_broadcast)
+ {
+ _input1_data = div_float_with_broadcasting::input1_data;
+ _input2_data = div_float_with_broadcasting::input2_data;
+ _reference_output_data = div_float_with_broadcasting::reference_output_data;
+ _test_kernel_model_circle = div_float_with_broadcasting::test_kernel_model_circle;
+ }
+ else
+ {
+ _input1_data = div_float_no_broadcasting::input1_data;
+ _input2_data = div_float_no_broadcasting::input2_data;
+ _reference_output_data = div_float_no_broadcasting::reference_output_data;
+ _test_kernel_model_circle = div_float_no_broadcasting::test_kernel_model_circle;
+ }
+ }
+
+ ~TestDataFloatDiv() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_DIV_KERNEL_FLOAT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/div/NegDivKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/div/NegDivKernel.h
new file mode 100644
index 000000000..df42f95fe
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/div/NegDivKernel.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_DIV_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_DIV_KERNEL_H
+
+#include "TestDataDivBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace input_1_wrong_type
+{
+
+/*
+ * Div Kernel with input type mismatch:
+ *
+ * Input_1(2, 5) - Int32 Input_2(2, 1) - Float
+ * \ /
+ * Div(with broadcast)
+ * |
+ * Output(2, 5)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+} // namespace input_1_wrong_type
+
+namespace input_2_wrong_type
+{
+
+/*
+ * DIV Kernel with input type mismatch:
+ *
+ * Input_1(2, 5)- Float Input_2(2, 1) - Int32
+ * \ /
+ * Div(with broadcast)
+ * |
+ * Output(2, 5)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+} // namespace input_2_wrong_type
+
+class NegTestDataInput1WrongTypeDiv : public NegTestDataBase
+{
+public:
+ NegTestDataInput1WrongTypeDiv()
+ {
+ _test_kernel_model_circle = input_1_wrong_type::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInput1WrongTypeDiv() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInput2WrongTypeDiv : public NegTestDataBase
+{
+public:
+ NegTestDataInput2WrongTypeDiv()
+ {
+ _test_kernel_model_circle = input_2_wrong_type::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInput2WrongTypeDiv() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_DIV_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/div/TestDataDivBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/div/TestDataDivBase.h
new file mode 100644
index 000000000..e4894e1ae
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/div/TestDataDivBase.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_DIV_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_DIV_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataDivBase : public TestDataBase<T>
+{
+public:
+ explicit TestDataDivBase(bool)
+ {
+ // Do nothing
+ }
+
+ TestDataDivBase() = delete;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input1_data;
+ case 1:
+ return _input2_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input1_data;
+ std::vector<T> _input2_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_DIV_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/elu/FloatEluKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/elu/FloatEluKernel.h
new file mode 100644
index 000000000..688933c49
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/elu/FloatEluKernel.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_FLOAT_ELU_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_ELU_KERNEL_H
+
+#include "TestDataEluBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace elu_float
+{
+/*
+ * Elu Kernel:
+ *
+ * Input(1, 3, 3, 2)
+ * |
+ * Elu
+ * |
+ * Output(1, 3, 3, 2)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff,
+ 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {-10.526339, -13.810211, -15.052563, -8.425814, 3.6157331,
+ 6.429944, -11.151951, 7.7377386, -2.4822063, 0.17121133,
+ 3.6448252, -6.6318836, 1.5882887, -4.6597095, 12.6291065,
+ -3.8438618, -2.5688074, -4.7900896};
+
+const std::vector<float> reference_output_data = {
+ -0.9999732, -0.999999, -0.9999997, -0.9997809, 3.6157331, 6.429944,
+ -0.99998564, 7.7377386, -0.9164414, 0.17121133, 3.6448252, -0.9986823,
+ 1.5882887, -0.9905308, 12.6291065, -0.97858924, -0.9233731, -0.9916883};
+
+} // namespace elu_float
+
+class TestDataFloatElu : public TestDataEluBase<float>
+{
+public:
+ TestDataFloatElu()
+ {
+ _input_data = elu_float::input_data;
+ _reference_output_data = elu_float::reference_output_data;
+ _test_kernel_model_circle = elu_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatElu() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_ELU_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/elu/NegEluKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/elu/NegEluKernel.h
new file mode 100644
index 000000000..db7ad33ac
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/elu/NegEluKernel.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_ELU_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_ELU_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_kernel
+{
+/*
+ * Elu Kernel with input output type mismatch:
+ *
+ * Input(1, 3, 3, 2) - Float32
+ * |
+ * Elu
+ * |
+ * Output(1, 3, 3, 2) - Int32
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff,
+ 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_input_output_type_mismatch_kernel
+
+class NegTestDataInputOutputTypeMismatchEluKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInputOutputTypeMismatchEluKernel()
+ {
+ _test_kernel_model_circle = neg_input_output_type_mismatch_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInputOutputTypeMismatchEluKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_ELU_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/elu/TestDataEluBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/elu/TestDataEluBase.h
new file mode 100644
index 000000000..50422374c
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/elu/TestDataEluBase.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_ELU_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_ELU_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataEluBase : public TestDataBase<T>
+{
+public:
+ TestDataEluBase() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_ELU_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/equal/FloatEqualKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/equal/FloatEqualKernel.h
new file mode 100644
index 000000000..1fce14f47
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/equal/FloatEqualKernel.h
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_EQUAL_KERNEL_FLOAT_H
+#define LUCI_INTERPRETER_TEST_MODELS_EQUAL_KERNEL_FLOAT_H
+
+#include "TestDataEqualBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+namespace neg_equal_float_with_no_broadcasting
+{
+
+/*
+ * Equal Kernel with input type mismatch
+ *
+ * Input_1(1, 4, 4, 3)-Float32 Input_2(1, 4, 4, 3)-Int32
+ * \ /
+ * Equal(no broadcast)
+ * |
+ * Output(1, 4, 4, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input1_data = {};
+
+const std::vector<float> input2_data = {};
+
+const std::vector<bool> reference_output_data = {};
+
+} // namespace neg_equal_float_with_no_broadcasting
+
+namespace equal_float_with_no_broadcasting
+{
+
+/*
+ * Equal Kernel:
+ *
+ * Input_1(2, 5) Input_2(2, 5)
+ * \ /
+ * Equal(no broadcast)
+ * |
+ * Output(2, 5)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
+ 0x3c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xd8, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input1_data = {0.0, 33.11, -1.1, 0.0, 5.5, -2.0, 0.0, -1.0, -4.5, 1.1};
+
+const std::vector<float> input2_data = {0.0, 33.11, 1.2, 0.0, 5.5, -2.0, 0.01, -1.0, -4.5, 1.12};
+
+const std::vector<bool> reference_output_data = {true, true, false, true, true,
+ true, false, true, true, false};
+
+} // namespace equal_float_with_no_broadcasting
+
+namespace equal_float_with_broadcasting
+{
+
+/*
+ * Equal Kernel:
+ *
+ * Input_1(2, 5) Input_2(1, 5)
+ * \ /
+ * Equal(with broadcast)
+ * |
+ * Output(2, 5)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
+ 0x3c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xd8, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input1_data = {-0.0, 0.0, -0.0, 0.0, 0.0, -0.0, 0.0, -0.0, -0.0, 0.0};
+
+const std::vector<float> input2_data = {0.0, -0.0, -0.0, 0.0, -0.0};
+
+const std::vector<bool> reference_output_data = {true, true, true, true, true,
+ true, true, true, true, true};
+
+} // namespace equal_float_with_broadcasting
+
+namespace neg_equal_float_with_broadcasting
+{
+
+/*
+ * Equal Kernel with input type mismatch:
+ *
+ * Input_1(2, 5)-float Input_2(1, 5)-Int32
+ * \ /
+ * Equal(with broadcast)
+ * |
+ * Output(2, 5)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
+ 0x3c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xd8, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input1_data = {};
+
+const std::vector<float> input2_data = {};
+
+const std::vector<bool> reference_output_data = {};
+
+} // namespace neg_equal_float_with_broadcasting
+
+class TestDataFloatEqual : public TestDataEqualBase<float, bool>
+{
+public:
+ explicit TestDataFloatEqual(bool is_with_broadcast, bool is_neg)
+ : TestDataEqualBase<float, bool>(is_with_broadcast)
+ {
+ if (not is_with_broadcast)
+ {
+ if (is_neg)
+ {
+ _input1_data = neg_equal_float_with_no_broadcasting::input1_data;
+ _input2_data = neg_equal_float_with_no_broadcasting::input2_data;
+ _reference_output_data = neg_equal_float_with_no_broadcasting::reference_output_data;
+ _test_kernel_model_circle = neg_equal_float_with_no_broadcasting::test_kernel_model_circle;
+ }
+ else
+ {
+ _input1_data = equal_float_with_no_broadcasting::input1_data;
+ _input2_data = equal_float_with_no_broadcasting::input2_data;
+ _reference_output_data = equal_float_with_no_broadcasting::reference_output_data;
+ _test_kernel_model_circle = equal_float_with_no_broadcasting::test_kernel_model_circle;
+ }
+ }
+ else
+ {
+ if (is_neg)
+ {
+ _input1_data = neg_equal_float_with_broadcasting::input1_data;
+ _input2_data = neg_equal_float_with_broadcasting::input2_data;
+ _reference_output_data = neg_equal_float_with_broadcasting::reference_output_data;
+ _test_kernel_model_circle = neg_equal_float_with_broadcasting::test_kernel_model_circle;
+ }
+ else
+ {
+ _input1_data = equal_float_with_broadcasting::input1_data;
+ _input2_data = equal_float_with_broadcasting::input2_data;
+ _reference_output_data = equal_float_with_broadcasting::reference_output_data;
+ _test_kernel_model_circle = equal_float_with_broadcasting::test_kernel_model_circle;
+ }
+ }
+ }
+
+ ~TestDataFloatEqual() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_EQUAL_KERNEL_FLOAT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/equal/IntEqualKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/equal/IntEqualKernel.h
new file mode 100644
index 000000000..964ad6dc2
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/equal/IntEqualKernel.h
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_EQUAL_KERNEL_INT_H
+#define LUCI_INTERPRETER_TEST_MODELS_EQUAL_KERNEL_INT_H
+
+#include "TestDataEqualBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace equal_int_with_no_broadcasting
+{
+
+/*
+ * Equal Kernel:
+ *
+ * Input_1(1, 5) Input_2(1, 5)
+ * \ /
+ * Equal(no broadcast)
+ * |
+ * Output(1, 5)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xac, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0xd4, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<int32_t> input1_data = {22, 31, 14, 5, 3};
+
+const std::vector<int32_t> input2_data = {3, 14, 14, 5, 5};
+
+const std::vector<bool> reference_output_data = {false, false, true, true, false};
+
+} // namespace equal_int_with_no_broadcasting
+
+namespace neg_equal_int_with_no_broadcasting
+{
+
+/*
+ * Equal Kernel with input type mismatch:
+ *
+ * Input_1(1, 5)-int Input_2(1, 5)-float
+ * \ /
+ * Equal(no broadcast)
+ * |
+ * Output(1, 5)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
+ 0x3c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa4, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<int32_t> input1_data = {};
+
+const std::vector<int32_t> input2_data = {};
+
+const std::vector<bool> reference_output_data = {};
+
+} // namespace neg_equal_int_with_no_broadcasting
+
+namespace equal_int_with_broadcasting
+{
+/*
+ * Equal Kernel:
+ *
+ * Input_1(2, 5) Input_2(1, 5)
+ * \ /
+ * Equal(with broadcast)
+ * |
+ * Output(2, 5)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xac, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0xd4, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<int32_t> input1_data = {12, 0, 0, -12, 0, 0, 12, -12, 0, -12};
+
+const std::vector<int32_t> input2_data = {0, 12, 0, 0, 0};
+
+const std::vector<bool> reference_output_data = {false, false, true, false, true,
+ true, true, false, true, false};
+
+} // namespace equal_int_with_broadcasting
+
+namespace neg_equal_int_with_broadcasting
+{
+
+/*
+ * Equal Kernel with input type mismatch:
+ *
+ * Input_1(2, 5) Input_2(1, 5)
+ * \ /
+ * Equal(with broadcast)
+ * |
+ * Output(2, 5)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
+ 0x3c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa4, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<int32_t> input1_data = {};
+
+const std::vector<int32_t> input2_data = {};
+
+const std::vector<bool> reference_output_data = {};
+
+} // namespace neg_equal_int_with_broadcasting
+
+class TestDataIntEqual : public TestDataEqualBase<int32_t, bool>
+{
+public:
+ explicit TestDataIntEqual(bool is_with_broadcast, bool is_neg)
+ : TestDataEqualBase<int32_t, bool>(is_with_broadcast)
+ {
+ if (is_with_broadcast)
+ {
+ if (is_neg)
+ {
+ _input1_data = neg_equal_int_with_broadcasting::input1_data;
+ _input2_data = neg_equal_int_with_broadcasting::input2_data;
+ _reference_output_data = neg_equal_int_with_broadcasting::reference_output_data;
+ _test_kernel_model_circle = neg_equal_int_with_broadcasting::test_kernel_model_circle;
+ }
+ else
+ {
+ _input1_data = equal_int_with_broadcasting::input1_data;
+ _input2_data = equal_int_with_broadcasting::input2_data;
+ _reference_output_data = equal_int_with_broadcasting::reference_output_data;
+ _test_kernel_model_circle = equal_int_with_broadcasting::test_kernel_model_circle;
+ }
+ }
+ else
+ {
+ if (is_neg)
+ {
+ _input1_data = neg_equal_int_with_no_broadcasting::input1_data;
+ _input2_data = neg_equal_int_with_no_broadcasting::input2_data;
+ _reference_output_data = neg_equal_int_with_no_broadcasting::reference_output_data;
+ _test_kernel_model_circle = neg_equal_int_with_no_broadcasting::test_kernel_model_circle;
+ }
+ else
+ {
+ _input1_data = equal_int_with_no_broadcasting::input1_data;
+ _input2_data = equal_int_with_no_broadcasting::input2_data;
+ _reference_output_data = equal_int_with_no_broadcasting::reference_output_data;
+ _test_kernel_model_circle = equal_int_with_no_broadcasting::test_kernel_model_circle;
+ }
+ }
+ }
+
+ ~TestDataIntEqual() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_LESS_KERNEL_INT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/equal/TestDataEqualBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/equal/TestDataEqualBase.h
new file mode 100644
index 000000000..c790f271d
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/equal/TestDataEqualBase.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_EQUAL_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_EQUAL_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T, typename U> class TestDataEqualBase : public TestDataBase<T, U>
+{
+public:
+ explicit TestDataEqualBase(bool)
+ {
+ // Do nothing
+ }
+
+ TestDataEqualBase() = delete;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input1_data;
+ case 1:
+ return _input2_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<U> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input1_data;
+ std::vector<T> _input2_data;
+ std::vector<U> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_EQUAL_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/exp/FloatExpKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/exp/FloatExpKernel.h
new file mode 100644
index 000000000..25370b3ab
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/exp/FloatExpKernel.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_FLOAT_EXP_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_EXP_KERNEL_H
+
+#include "TestDataExpBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace exp_float
+{
+/*
+ * Exp Kernel:
+ *
+ * Input(1, 3, 3, 2)
+ * |
+ * Exp
+ * |
+ * Output(1, 3, 3, 2)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff,
+ 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x21, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {-18.223001, 5.126108, -14.195034, 14.899473, -5.9829874,
+ 4.536052, 6.039304, 6.410294, -7.008984, -16.432007,
+ 15.697407, -1.1735272, -2.2951646, -1.262989, 7.4088907,
+ 0.24651751, -10.7505045, 4.2837596};
+const std::vector<float> reference_output_data = {
+ 1.2185715e-08, 168.36061, 6.8418734e-07, 2956371.5, 0.002521283, 93.32166,
+ 419.6008, 608.07245, 0.0009037262, 7.305839e-08, 6565943.5, 0.30927414,
+ 0.10074481, 0.28280744, 1650.5944, 1.2795616, 2.1434593e-05, 72.51254};
+
+} // namespace exp_float
+
+class TestDataFloatExp : public TestDataExpBase<float>
+{
+public:
+ TestDataFloatExp()
+ {
+ _input_data = exp_float::input_data;
+ _reference_output_data = exp_float::reference_output_data;
+ _test_kernel_model_circle = exp_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatExp() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_EXP_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/exp/NegExpKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/exp/NegExpKernel.h
new file mode 100644
index 000000000..ed31853ae
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/exp/NegExpKernel.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_EXP_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_EXP_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_kernel
+{
+/*
+ * Exp Kernel with input output type mismatch:
+ *
+ * Input(1, 3, 3, 2) - Float32
+ * |
+ * Exp
+ * |
+ * Output(1, 3, 3, 2) - Int32
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff,
+ 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x21, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_input_output_type_mismatch_kernel
+
+class NegTestDataInputOutputTypeMismatchExpKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInputOutputTypeMismatchExpKernel()
+ {
+ _test_kernel_model_circle = neg_input_output_type_mismatch_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInputOutputTypeMismatchExpKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_EXP_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/exp/TestDataExpBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/exp/TestDataExpBase.h
new file mode 100644
index 000000000..6427096e3
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/exp/TestDataExpBase.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_EXP_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_EXP_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataExpBase : public TestDataBase<T>
+{
+public:
+ TestDataExpBase() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_EXP_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/expand_dims/ExpandDimsKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/expand_dims/ExpandDimsKernel.h
new file mode 100644
index 000000000..010d972c5
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/expand_dims/ExpandDimsKernel.h
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_EXPAND_DIMS_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_EXPAND_DIMS_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+namespace neg_test_expand_dims
+{
+
+/*
+ * ExpandDims Kernel:
+ *
+ * Input(3, 3) Const([1]) - wrong type for const
+ * | /
+ * ExpandDims
+ * |
+ * Output(3, 1, 3)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff,
+ 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34,
+ 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
+ 0x3c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa8, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_test_expand_dims
+
+namespace expand_dims_kernel
+{
+/*
+ * ExpandDims Kernel:
+ *
+ * Input(3, 3) Const([1])
+ * | /
+ * ExpandDims
+ * |
+ * Output(3, 1, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff,
+ 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34,
+ 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
+ 0x3c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa8, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {10.438837, -1.168417, -6.455261, -1.3638954, 31.58745,
+ 29.395872, -10.366383, 7.6131954, 9.837751};
+
+const std::vector<float> reference_output_data = {10.438837, -1.168417, -6.455261,
+ -1.3638954, 31.58745, 29.395872,
+ -10.366383, 7.6131954, 9.837751};
+
+} // namespace expand_dims_kernel
+
+template <typename T> class TestDataExpandDimsKernel : public TestDataBase<T>
+{
+public:
+ TestDataExpandDimsKernel()
+ {
+ _input_data = expand_dims_kernel::input_data;
+ _reference_output_data = expand_dims_kernel::reference_output_data;
+ _test_kernel_model_circle = expand_dims_kernel::test_kernel_model_circle;
+ }
+
+ ~TestDataExpandDimsKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInvalidInputTypeExpandDimsKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInvalidInputTypeExpandDimsKernel()
+ {
+ _test_kernel_model_circle = neg_test_expand_dims::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInvalidInputTypeExpandDimsKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_EXPAND_DIMS_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/fill/FillKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/fill/FillKernel.h
new file mode 100644
index 000000000..e567361ba
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/fill/FillKernel.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_FILL_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FILL_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace fill_kernel
+{
+/*
+ * Fill Kernel:
+ *
+ * Dims(3, 2) Input(scalar)
+ * \ /
+ * Fill
+ * |
+ * |
+ * Output(3, 2)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff,
+ 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
+ 0x64, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x64, 0x69, 0x6d, 0x73, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5e, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {1.1f};
+
+const std::vector<float> reference_output_data = {1.1f, 1.1f, 1.1f, 1.1f, 1.1f, 1.1f};
+} // namespace fill_kernel
+
+template <typename T> class TestDataFillKernel : public TestDataBase<T>
+{
+public:
+ TestDataFillKernel()
+ {
+ _input_data = fill_kernel::input_data;
+ _reference_output_data = fill_kernel::reference_output_data;
+ _test_kernel_model_circle = fill_kernel::test_kernel_model_circle;
+ }
+
+ ~TestDataFillKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FILL_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/fill/NegFillKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/fill/NegFillKernel.h
new file mode 100644
index 000000000..85f0e70a5
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/fill/NegFillKernel.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_FILL_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_FILL_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_fill_kernel
+{
+/*
+ * Fill Kernel with input output type mismatch (should be equal):
+ *
+ * Dims(3, 2) -Float32 Input(scalar) - Float32
+ * \ /
+ * Fill
+ * |
+ * |
+ * Output(3, 2) - Int32
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x4c, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xa4, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x76, 0x61, 0x6c, 0x75,
+ 0x65, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x64, 0x69, 0x6d, 0x73, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_input_output_type_mismatch_fill_kernel
+
+namespace neg_wrong_input_shape_fill_kernel
+{
+/*
+ * Fill Kernel with input wrong shape (should be scalar):
+ *
+ * Dims(3, 2) -Float32 Input(5) - Float32
+ * \ /
+ * Fill
+ * |
+ * |
+ * Output(3, 2) - Float32
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x4c, 0x00, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xd8, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x64, 0x69, 0x6d, 0x73,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_wrong_input_shape_fill_kernel
+
+class NegTestDataInputTypeMismatchFillKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInputTypeMismatchFillKernel()
+ {
+ _test_kernel_model_circle =
+ neg_input_output_type_mismatch_fill_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInputTypeMismatchFillKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataWrongInputShapeFillKernel : public NegTestDataBase
+{
+public:
+ NegTestDataWrongInputShapeFillKernel()
+ {
+ _test_kernel_model_circle = neg_wrong_input_shape_fill_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataWrongInputShapeFillKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_FILL_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/fully_connected/FloatFullyConnectedKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/fully_connected/FloatFullyConnectedKernel.h
new file mode 100644
index 000000000..55ee09fc3
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/fully_connected/FloatFullyConnectedKernel.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_FULLY_CONNECTED_KERNEL_FLOAT_H
+#define LUCI_INTERPRETER_TEST_MODELS_FULLY_CONNECTED_KERNEL_FLOAT_H
+
+#include "TestDataFullyConnectedBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace fully_connected_float
+{
+
+/*
+ * FullyConnected Kernel:
+ *
+ * Input(1, 16) Weight(4, 16) Bias(4)
+ * \ | /
+ * \ | /
+ * FullyConnected
+ * |
+ * Output(1, 4)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x60, 0x01, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0xc4, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x4c, 0x01, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x3c, 0x01, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xe2, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x40, 0xc0, 0x00, 0x00, 0x80, 0x40,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0xc0,
+ 0x00, 0x00, 0x80, 0xc0, 0x00, 0x00, 0xa0, 0xc0, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0xe0, 0xc0,
+ 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x40, 0x40,
+ 0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0xe0, 0x40,
+ 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0xc0,
+ 0x00, 0x00, 0x80, 0xc0, 0x00, 0x00, 0xa0, 0xc0, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0xe0, 0xc0,
+ 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x40, 0x40,
+ 0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0xe0, 0x40,
+ 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0xc0,
+ 0x00, 0x00, 0x80, 0xc0, 0x00, 0x00, 0xa0, 0xc0, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0xe0, 0xc0,
+ 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x40, 0x40,
+ 0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0xe0, 0x40,
+ 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0xc0,
+ 0x00, 0x00, 0x80, 0xc0, 0x00, 0x00, 0xa0, 0xc0, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0xe0, 0xc0,
+ 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x40, 0x40,
+ 0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0xe0, 0x40,
+ 0x00, 0x00, 0xa0, 0x40, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00,
+ 0x54, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x90, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x75, 0x74, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xb4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xd8, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {
+ 17.491695, 15.660671, 4.7347794, -15.796822, 20.4776, 18.438372, -0.7529831, 10.671711,
+ 10.699566, 3.1682281, -22.776001, 1.527811, -0.1198349, -5.748741, -5.1772327, 20.06879};
+
+const std::vector<float> reference_output_data = {263.84323, 260.84323, 259.84323, 266.84323};
+
+} // namespace fully_connected_float
+
+class TestDataFloatFullyConnected : public TestDataFullyConnectedBase<float>
+{
+public:
+ TestDataFloatFullyConnected()
+ {
+ _input_data = fully_connected_float::input_data;
+ _reference_output_data = fully_connected_float::reference_output_data;
+ _test_kernel_model_circle = fully_connected_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatFullyConnected() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FULLY_CONNECTED_KERNEL_FLOAT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/fully_connected/NegFullyConnectedKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/fully_connected/NegFullyConnectedKernel.h
new file mode 100644
index 000000000..785c4ce3e
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/fully_connected/NegFullyConnectedKernel.h
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_FULLY_CONNECTED_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_FULLY_CONNECTED_KERNEL_H
+
+#include "TestDataFullyConnectedBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_fully_connected_wrong_weight_type
+{
+/*
+ * FullyConnected Kernel with wrong weight type (Int16):
+ *
+ * Input(1, 4) Weight(4, 4) - Int16 Bias(4)
+ * \ | /
+ * \ | /
+ * FullyConnected
+ * |
+ * Output(1, 4)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0xb4, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x84, 0xff, 0xff, 0xff, 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff,
+ 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x75, 0x74, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0xa4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+ 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_fully_connected_wrong_weight_type
+
+namespace neg_fully_connected_wrong_weight_shape
+{
+/*
+ * FullyConnected Kernel with wrong weight shape (rank should be 2):
+ *
+ * Input(1, 64) Weight(1, 8, 64) Bias(8)
+ * \ | /
+ * \ | /
+ * FullyConnected
+ * |
+ * Output(1, 8)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x84, 0xff, 0xff, 0xff, 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff,
+ 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00,
+ 0x54, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x75, 0x74, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0xb0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x69, 0x6e, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_fully_connected_wrong_weight_shape
+
+namespace neg_fully_connected_wrong_bias_shape
+{
+/*
+ * FullyConnected Kernel with wrong bias shape should be equal to output.dim(1):
+ *
+ * Input(1, 64) Weight(1, 8, 64) Bias(15)
+ * \ | /
+ * \ | /
+ * FullyConnected
+ * |
+ * Output(1, 8)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00, 0xa4, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x84, 0xff, 0xff, 0xff, 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff,
+ 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00,
+ 0x54, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x90, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x75, 0x74, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0xb4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x0f, 0x00, 0x00, 0x00, 0xd8, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_fully_connected_wrong_bias_shape
+
+class NegTestDataWrongWeightTypeFullyConnectedKernel : public NegTestDataBase
+{
+public:
+ NegTestDataWrongWeightTypeFullyConnectedKernel()
+ {
+ _test_kernel_model_circle = neg_fully_connected_wrong_weight_type::test_kernel_model_circle;
+ }
+
+ ~NegTestDataWrongWeightTypeFullyConnectedKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataWrongWeightShapeFullyConnectedKernel : public NegTestDataBase
+{
+public:
+ NegTestDataWrongWeightShapeFullyConnectedKernel()
+ {
+ _test_kernel_model_circle = neg_fully_connected_wrong_weight_shape::test_kernel_model_circle;
+ }
+
+ ~NegTestDataWrongWeightShapeFullyConnectedKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataWrongBiasShapeFullyConnectedKernel : public NegTestDataBase
+{
+public:
+ NegTestDataWrongBiasShapeFullyConnectedKernel()
+ {
+ _test_kernel_model_circle = neg_fully_connected_wrong_bias_shape::test_kernel_model_circle;
+ }
+
+ ~NegTestDataWrongBiasShapeFullyConnectedKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_FULLY_CONNECTED_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/fully_connected/TestDataFullyConnectedBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/fully_connected/TestDataFullyConnectedBase.h
new file mode 100644
index 000000000..582b3db40
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/fully_connected/TestDataFullyConnectedBase.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_FULLY_CONNECTED_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_FULLY_CONNECTED_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataFullyConnectedBase : public TestDataBase<T>
+{
+public:
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FULLY_CONNECTED_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/fully_connected/U8FullyConnectedKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/fully_connected/U8FullyConnectedKernel.h
new file mode 100644
index 000000000..f5d970600
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/fully_connected/U8FullyConnectedKernel.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_FULLY_CONNECTED_KERNEL_U8_H
+#define LUCI_INTERPRETER_TEST_MODELS_FULLY_CONNECTED_KERNEL_U8_H
+
+#include "TestDataFullyConnectedBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace fully_connected_u8
+{
+
+/*
+ * FullyConnected Kernel:
+ *
+ * Input(1, 4) Weight(4, 4) Bias(4)
+ * \ | /
+ * \ | /
+ * FullyConnected
+ * |
+ * Output(1, 4)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x1c, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xa0, 0x02, 0x00, 0x00, 0xbc, 0x02, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe2, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x03, 0x16, 0x04, 0x2d, 0x17,
+ 0x0b, 0x2b, 0x05, 0x2c, 0x06, 0x2c, 0x4e, 0x6f, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff,
+ 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x24, 0x01, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xfa, 0xfe, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x44, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x99, 0x96, 0xfd, 0x3b,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+ 0x4c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00,
+ 0x84, 0xff, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf0, 0xf1, 0xae, 0x3b, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x54, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x68, 0x68, 0x2b, 0x3a, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<uint8_t> input_data = {5, 3, 251, 5};
+
+const std::vector<uint8_t> reference_output_data = {5, 10, 5, 13};
+
+} // namespace fully_connected_u8
+
+class TestDataU8FullyConnected : public TestDataFullyConnectedBase<uint8_t>
+{
+public:
+ TestDataU8FullyConnected()
+ {
+ _input_data = fully_connected_u8::input_data;
+ _reference_output_data = fully_connected_u8::reference_output_data;
+ _test_kernel_model_circle = fully_connected_u8::test_kernel_model_circle;
+ }
+
+ ~TestDataU8FullyConnected() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FULLY_CONNECTED_KERNEL_U8_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather/FloatGatherKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather/FloatGatherKernel.h
new file mode 100644
index 000000000..570ebbf02
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather/FloatGatherKernel.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_GATHER_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_GATHER_KERNEL_H
+
+#include "TestDataGatherBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace gather_float
+{
+/*
+ * Gather Kernel:
+ *
+ * Input(1, 2, 3, 4) Indices(1, 2)
+ * \ /
+ * Gather(axis=2)
+ * |
+ * Output(1, 2, 2, 4)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00, 0xa4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x72, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x70, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17,
+ 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xa0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {
+ -21.338402, 27.906258, 12.78171, 9.978121, 25.450222, -11.091215, -8.654621, 1.2170105,
+ -4.5460815, 19.334154, 6.8392344, 5.622982, 2.2990818, -8.733818, 8.312399, -2.8866997,
+ 13.171104, 3.4856339, -17.577343, 20.683546, 1.0197582, 27.619759, -6.016859, -4.398407};
+
+const std::vector<float> reference_output_data = {
+ 25.450222, -11.091215, -8.654621, 1.2170105, -4.5460815, 19.334154, 6.8392344, 5.622982,
+ 13.171104, 3.4856339, -17.577343, 20.683546, 1.0197582, 27.619759, -6.016859, -4.398407};
+
+} // namespace gather_float
+
+class TestDataFloatGather : public TestDataGatherBase<float>
+{
+public:
+ TestDataFloatGather()
+ {
+ _input_data = gather_float::input_data;
+ _reference_output_data = gather_float::reference_output_data;
+ _test_kernel_model_circle = gather_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatGather() override = default;
+};
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_GATHER_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather/IntGatherKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather/IntGatherKernel.h
new file mode 100644
index 000000000..5c7edef11
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather/IntGatherKernel.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_GATHER_INT_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_GATHER_INT_KERNEL_H
+
+#include "TestDataGatherBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace gather_int
+{
+/*
+ * Gather Kernel:
+ *
+ * Input(1, 2, 3, 4) Indices(1, 2)
+ * \ /
+ * Gather(axis=2)
+ * |
+ * Output(1, 2, 2, 4)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x72, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x70, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17,
+ 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xa8, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xd8, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61,
+ 0x6d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<int> input_data = {4, 14, 14, 22, 5, -5, -4, -3, 5, 15, 13, 5,
+ -3, 5, -13, 15, -6, -13, -4, -12, -5, 5, 5, -5};
+
+const std::vector<int> reference_output_data = {5, -5, -4, -3, 5, 15, 13, 5,
+ -6, -13, -4, -12, -5, 5, 5, -5};
+
+} // namespace gather_int
+
+class TestDataIntGather : public TestDataGatherBase<int>
+{
+public:
+ TestDataIntGather()
+ {
+ _input_data = gather_int::input_data;
+ _reference_output_data = gather_int::reference_output_data;
+ _test_kernel_model_circle = gather_int::test_kernel_model_circle;
+ }
+
+ ~TestDataIntGather() override = default;
+};
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_GATHER_INT_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather/NegGatherKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather/NegGatherKernel.h
new file mode 100644
index 000000000..a902b7288
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather/NegGatherKernel.h
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_GATHER_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_GATHER_KERNEL_H
+
+#include "TestDataGatherBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_gather_mismatch_input_output_type
+{
+/*
+ * Gather Kernel with input output type mismatch (should be equal):
+ *
+ * Input(1, 2, 3, 4) - S16 Indices(1, 2)
+ * \ /
+ * Gather(axis=2)
+ * |
+ * Output(1, 2, 2, 4) - Float32
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x72, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x70, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17,
+ 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xd8, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+} // namespace neg_gather_mismatch_input_output_type
+
+namespace neg_gather_wrong_position_type
+{
+/*
+ * Gather Kernel with wrong Indices type(should be S32):
+ *
+ * Input(1, 2, 3, 4) - S16 Indices(1, 2) - Float32
+ * \ /
+ * Gather(axis=2)
+ * |
+ * Output(1, 2, 2, 4) - Float32
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x72, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
+ 0x00, 0x00, 0x00, 0x40, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x70, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17,
+ 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xb0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xdc, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+} // namespace neg_gather_wrong_position_type
+
+namespace neg_gather_wrong_axis
+{
+/*
+ * Gather Kernel with wrong axis value(should be < rank(input)):
+ *
+ * Input(1, 2, 3, 4) - S16 Indices(1, 2) - Float32
+ * \ /
+ * Gather(axis=10)
+ * |
+ * Output(1, 2, 2, 4) - Float32
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00, 0xa4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x72, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x70, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17,
+ 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xa0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+} // namespace neg_gather_wrong_axis
+
+class NegTestDataInputOutputTypeMismatchGatherKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInputOutputTypeMismatchGatherKernel()
+ {
+ _test_kernel_model_circle = neg_gather_mismatch_input_output_type::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInputOutputTypeMismatchGatherKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataWrongPositionTypeGatherKernel : public NegTestDataBase
+{
+public:
+ NegTestDataWrongPositionTypeGatherKernel()
+ {
+ _test_kernel_model_circle = neg_gather_wrong_position_type::test_kernel_model_circle;
+ }
+
+ ~NegTestDataWrongPositionTypeGatherKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataWrongAxisGatherKernel : public NegTestDataBase
+{
+public:
+ NegTestDataWrongAxisGatherKernel()
+ {
+ _test_kernel_model_circle = neg_gather_wrong_axis::test_kernel_model_circle;
+ }
+
+ ~NegTestDataWrongAxisGatherKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_GATHER_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather/TestDataGatherBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather/TestDataGatherBase.h
new file mode 100644
index 000000000..e38fcb86e
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather/TestDataGatherBase.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_GATHER_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_GATHER_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataGatherBase : public TestDataBase<T>
+{
+public:
+ TestDataGatherBase() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_GATHER_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/greater/FloatGreaterKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/greater/FloatGreaterKernel.h
new file mode 100644
index 000000000..dcb7b6886
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/greater/FloatGreaterKernel.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_GREATER_KERNEL_FLOAT_H
+#define LUCI_INTERPRETER_TEST_MODELS_GREATER_KERNEL_FLOAT_H
+
+#include "TestDataGreaterBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace greater_float
+{
+
+/*
+ * Greater Kernel:
+ *
+ * Input_1(1, 4, 4, 3) Input_2(1, 4, 4, 3)
+ * \ /
+ * Greater(no broadcast)
+ * |
+ * Output(1, 4, 4, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input1_data = {
+ -0.01787583, -0.8314556, -0.47624078, -1.9747407, -0.51676583, -0.20183715, -1.9358647,
+ 0.7616414, -0.0899037, 2.048367, -1.3174965, 1.5267943, 0.68707687, 1.3464743,
+ 0.98674047, -1.4853697, 1.9973947, 0.5170953, 0.37471953, -1.6011852, 0.32045737,
+ -0.6598305, -1.7946662, 1.2349467, 1.3320708, 0.5151753, 1.345111, -0.16560331,
+ 0.82792366, -1.734876, 0.043626763, -0.0118546495, 0.31535238, 0.1888555, -0.32523626,
+ -0.997665, 0.5819472, -2.3194845, -1.6897905, 0.9981752, -1.2897044, 0.75768864,
+ 0.56781554, -1.0565805, -1.4891449, 0.2493645, -1.1312587, 0.6837854};
+
+const std::vector<float> input2_data = {
+ 0.30809638, -0.28285328, -0.8437058, 1.7689779, 0.5182942, 0.571205, -0.89484423,
+ 0.28100377, 0.5453497, 1.3848042, -0.04359268, -1.7448778, -0.5375435, -0.85059136,
+ -0.77961826, -0.4916915, 1.3359088, -0.09580261, 0.6158275, -0.05056348, 0.90505254,
+ 0.94226706, 1.136139, -0.45077038, -0.5018571, -1.1543767, 0.85094684, -0.13731039,
+ -0.3298641, 0.9474698, -0.48497504, -0.14864737, -0.009302358, -1.1259161, 0.44226727,
+ 1.0149708, 0.36024934, 0.4969523, 0.45014778, -0.34718898, 1.2260172, 0.35304692,
+ -1.3037513, -0.2565706, 0.18085766, -0.7099202, -0.9203537, -1.2257448};
+
+const std::vector<bool> reference_output_data = {
+ false, false, true, false, false, false, false, true, false, true, false, true,
+ true, true, true, false, true, true, false, false, false, false, false, true,
+ true, true, true, false, true, false, true, true, true, true, false, false,
+ true, false, false, true, false, true, true, false, false, true, false, true};
+
+} // namespace greater_float
+
+namespace neg_greater_float_with_no_broadcasting
+{
+
+/*
+ * Greater Kernel with input type mismatch:
+ *
+ * Input_1(1, 4, 4, 3)-float Input_2(1, 4, 4, 3)-int
+ * \ /
+ * Greater(no broadcast)
+ * |
+ * Output(1, 4, 4, 3)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3d, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input1_data = {};
+
+const std::vector<float> input2_data = {};
+
+const std::vector<bool> reference_output_data = {};
+
+} // namespace neg_greater_float_with_no_broadcasting
+
+class TestDataFloatGreater : public TestDataGreaterBase<float, bool>
+{
+public:
+ explicit TestDataFloatGreater(bool is_with_broadcast, bool is_neg)
+ : TestDataGreaterBase<float, bool>(is_with_broadcast)
+ {
+ if (is_with_broadcast)
+ {
+ assert(false && "Not impl yet");
+ }
+ else
+ {
+ if (is_neg)
+ {
+ _input1_data = neg_greater_float_with_no_broadcasting::input1_data;
+ _input2_data = neg_greater_float_with_no_broadcasting::input2_data;
+ _reference_output_data = neg_greater_float_with_no_broadcasting::reference_output_data;
+ _test_kernel_model_circle =
+ neg_greater_float_with_no_broadcasting::test_kernel_model_circle;
+ }
+ else
+ {
+ _input1_data = greater_float::input1_data;
+ _input2_data = greater_float::input2_data;
+ _reference_output_data = greater_float::reference_output_data;
+ _test_kernel_model_circle = greater_float::test_kernel_model_circle;
+ }
+ }
+ }
+
+ ~TestDataFloatGreater() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_GREATER_KERNEL_FLOAT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/greater/TestDataGreaterBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/greater/TestDataGreaterBase.h
new file mode 100644
index 000000000..7c2005a64
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/greater/TestDataGreaterBase.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_GREATER_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_GREATER_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T, typename U> class TestDataGreaterBase : public TestDataBase<T, U>
+{
+public:
+ explicit TestDataGreaterBase(bool)
+ {
+ // Do nothing
+ }
+
+ TestDataGreaterBase() = delete;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input1_data;
+ case 1:
+ return _input2_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<U> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input1_data;
+ std::vector<T> _input2_data;
+ std::vector<U> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_GREATER_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/greater_equal/FloatGreaterEqualKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/greater_equal/FloatGreaterEqualKernel.h
new file mode 100644
index 000000000..14226ab40
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/greater_equal/FloatGreaterEqualKernel.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_GREATER_EQUAL_KERNEL_FLOAT_H
+#define LUCI_INTERPRETER_TEST_MODELS_GREATER_EQUAL_KERNEL_FLOAT_H
+
+#include "TestDataGreaterEqualBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace greater_equal_float
+{
+
+/*
+ * GreaterEqual Kernel:
+ *
+ * Input_1(1, 4, 4, 3) Input_2(1, 4, 4, 3)
+ * \ /
+ * GreaterEqual(no broadcast)
+ * |
+ * Output(1, 4, 4, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input1_data = {
+ -0.01787583, -0.8314556, -0.47624078, -1.9747407, -0.51676583, -0.20183715, -1.9358647,
+ 0.7616414, -0.0899037, 2.048367, -1.3174965, 1.5267943, 0.68707687, 1.3464743,
+ 0.98674047, -1.4853697, 1.9973947, 0.5170953, 0.37471953, -1.6011852, 0.32045737,
+ -0.6598305, -1.7946662, 1.2349467, 1.3320708, 0.5151753, 1.345111, -0.16560331,
+ 0.82792366, -1.734876, 0.043626763, -0.0118546495, 0.31535238, 0.1888555, -0.32523626,
+ -0.997665, 0.5819472, -2.3194845, -1.6897905, 0.9981752, -1.2897044, 0.75768864,
+ 0.56781554, -1.0565805, -1.4891449, 0.2493645, -1.1312587, 0.6837854};
+
+const std::vector<float> input2_data = {
+ 0.30809638, -0.28285328, -0.8437058, 1.7689779, 0.5182942, 0.571205, -0.89484423,
+ 0.28100377, 0.5453497, 1.3848042, -0.04359268, -1.7448778, -0.5375435, -0.85059136,
+ -0.77961826, -0.4916915, 1.3359088, -0.09580261, 0.6158275, -0.05056348, 0.90505254,
+ 0.94226706, 1.136139, -0.45077038, -0.5018571, -1.1543767, 0.85094684, -0.13731039,
+ -0.3298641, 0.9474698, -0.48497504, -0.14864737, -0.009302358, -1.1259161, 0.44226727,
+ 1.0149708, 0.36024934, 0.4969523, 0.45014778, -0.34718898, 1.2260172, 0.35304692,
+ -1.3037513, -0.2565706, 0.18085766, -0.7099202, -0.9203537, -1.2257448};
+
+const std::vector<bool> reference_output_data = {
+ false, false, true, false, false, false, false, true, false, true, false, true,
+ true, true, true, false, true, true, false, false, false, false, false, true,
+ true, true, true, false, true, false, true, true, true, true, false, false,
+ true, false, false, true, false, true, true, false, false, true, false, true};
+
+} // namespace greater_equal_float
+
+namespace neg_greater_equal_float_with_no_broadcasting
+{
+
+/*
+ * GreaterEqual Kernel with input type mismatch:
+ *
+ * Input_1(1, 4, 4, 3)-float Input_2(1, 4, 4, 3)-int
+ * \ /
+ * GreaterEqual(no broadcast)
+ * |
+ * Output(1, 4, 4, 3)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+
+};
+
+const std::vector<float> input1_data = {};
+
+const std::vector<float> input2_data = {};
+
+const std::vector<bool> reference_output_data = {};
+
+} // namespace neg_greater_equal_float_with_no_broadcasting
+
+class TestDataFloatGreaterEqual : public TestDataGreaterEqualBase<float, bool>
+{
+public:
+ explicit TestDataFloatGreaterEqual(bool is_with_broadcast, bool is_neg)
+ : TestDataGreaterEqualBase<float, bool>(is_with_broadcast)
+ {
+ if (is_with_broadcast)
+ {
+ assert(false && "Not impl yet");
+ }
+ else
+ {
+ if (is_neg)
+ {
+ _input1_data = neg_greater_equal_float_with_no_broadcasting::input1_data;
+ _input2_data = neg_greater_equal_float_with_no_broadcasting::input2_data;
+ _reference_output_data =
+ neg_greater_equal_float_with_no_broadcasting::reference_output_data;
+ _test_kernel_model_circle =
+ neg_greater_equal_float_with_no_broadcasting::test_kernel_model_circle;
+ }
+ else
+ {
+ _input1_data = greater_equal_float::input1_data;
+ _input2_data = greater_equal_float::input2_data;
+ _reference_output_data = greater_equal_float::reference_output_data;
+ _test_kernel_model_circle = greater_equal_float::test_kernel_model_circle;
+ }
+ }
+ }
+
+ ~TestDataFloatGreaterEqual() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_GREATER_KERNEL_FLOAT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/greater_equal/TestDataGreaterEqualBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/greater_equal/TestDataGreaterEqualBase.h
new file mode 100644
index 000000000..9153c357a
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/greater_equal/TestDataGreaterEqualBase.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_GREATER_EQUAL_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_GREATER_EQUAL_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T, typename U> class TestDataGreaterEqualBase : public TestDataBase<T, U>
+{
+public:
+ explicit TestDataGreaterEqualBase(bool)
+ {
+ // Do nothing
+ }
+
+ TestDataGreaterEqualBase() = delete;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input1_data;
+ case 1:
+ return _input2_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<U> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input1_data;
+ std::vector<T> _input2_data;
+ std::vector<U> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_GREATER_EQUAL_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/leaky_relu/FloatLeakyReLUKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/leaky_relu/FloatLeakyReLUKernel.h
new file mode 100644
index 000000000..6d1e81f7a
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/leaky_relu/FloatLeakyReLUKernel.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_FLOAT_LEAKY_RELU_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_LEAKY_RELU_KERNEL_H
+
+#include "TestDataLeakyReLUBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace leaky_relu_float
+{
+/*
+ * Leaky_ReLU Kernel:
+ *
+ * Input(1, 3, 3, 2)
+ * |
+ * Leaky_ReLU
+ * |
+ * Output(1, 3, 3, 2)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff,
+ 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x64, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xd4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x62, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {-19.160503, 32.721092, 9.924562, -5.1152186, -4.792659,
+ 5.404521, 21.64431, 4.1435075, -9.379442, 10.986649,
+ -19.975468, -2.6520946, 9.306602, -12.589155, -2.9080758,
+ 21.732197, -2.6927, -2.0605793};
+
+const std::vector<float> reference_output_data = {
+ -38.321007, 32.721092, 9.924562, -10.230437, -9.585318, 5.404521,
+ 21.64431, 4.1435075, -18.758884, 10.986649, -39.950935, -5.304189,
+ 9.306602, -25.17831, -5.8161516, 21.732197, -5.3854, -4.1211586};
+
+} // namespace leaky_relu_float
+
+class TestDataFloatLeakyReLU : public TestDataLeakyReLUBase<float>
+{
+public:
+ TestDataFloatLeakyReLU()
+ {
+ _input_data = leaky_relu_float::input_data;
+ _reference_output_data = leaky_relu_float::reference_output_data;
+ _test_kernel_model_circle = leaky_relu_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatLeakyReLU() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_LEAKY_RELU_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/leaky_relu/NegLeakyReLUKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/leaky_relu/NegLeakyReLUKernel.h
new file mode 100644
index 000000000..1d6ebde76
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/leaky_relu/NegLeakyReLUKernel.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_LEAKY_RELU_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_LEAKY_RELU_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_kernel
+{
+/*
+ * LeakyReLU Kernel with input output type mismatch:
+ *
+ * Input(1, 3, 3, 2) - Float32
+ * |
+ * LeakyReLU
+ * |
+ * Output(1, 3, 3, 2) - Int32
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x5c, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff,
+ 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x64, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x62, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_input_output_type_mismatch_kernel
+
+class NegTestDataInputOutputTypeMismatchLeakyReLUKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInputOutputTypeMismatchLeakyReLUKernel()
+ {
+ _test_kernel_model_circle = neg_input_output_type_mismatch_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInputOutputTypeMismatchLeakyReLUKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_LEAKY_RELU_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/leaky_relu/TestDataLeakyReLUBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/leaky_relu/TestDataLeakyReLUBase.h
new file mode 100644
index 000000000..ed8346a3b
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/leaky_relu/TestDataLeakyReLUBase.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_LEAKY_RELU_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_LEAKY_RELU_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataLeakyReLUBase : public TestDataBase<T>
+{
+public:
+ TestDataLeakyReLUBase() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_LEAKY_RELU_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/less/FloatLessKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/less/FloatLessKernel.h
new file mode 100644
index 000000000..56556d1f4
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/less/FloatLessKernel.h
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_LESS_KERNEL_FLOAT_H
+#define LUCI_INTERPRETER_TEST_MODELS_LESS_KERNEL_FLOAT_H
+
+#include "TestDataLessBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+namespace neg_less_float_with_no_broadcasting
+{
+
+/*
+ * Less Kernel with input type mismatch
+ *
+ * Input_1(1, 4, 4, 3) Input_2(1, 4, 4, 3)
+ * \ /
+ * Less(no broadcast)
+ * |
+ * Output(1, 4, 4, 3)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x94, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3a, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input1_data = {};
+
+const std::vector<float> input2_data = {};
+
+const std::vector<bool> reference_output_data = {};
+
+} // namespace neg_less_float_with_no_broadcasting
+
+namespace less_float_with_no_broadcasting
+{
+
+/*
+ * Less Kernel:
+ *
+ * Input_1(1, 4, 4, 3) Input_2(1, 4, 4, 3)
+ * \ /
+ * Less(no broadcast)
+ * |
+ * Output(1, 4, 4, 3)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input1_data = {
+ -17.109156, -14.220402, 0.6967888, 8.5724945, -9.638723, -15.630436, 5.7072678, -28.719913,
+ 26.073956, 28.855093, -15.886295, -11.779518, 7.330929, -0.13710785, 15.124775, 9.482744,
+ 1.2159233, -11.10869, -7.9041195, 32.05063, 1.4171028, -9.373051, -3.7985916, -0.6265869,
+ 1.1357956, 1.3873901, -6.6756783, 7.348675, -3.1261578, 13.6670475, 13.453075, 2.7914486,
+ 24.654053, 23.756575, 3.0251846, -6.2888947, 15.202778, -6.0607758, 1.6703491, -18.499111,
+ 10.935091, 1.846302, -16.904373, 0.9744568, -1.1621361, -2.4073143, 4.1701775, 4.268633};
+
+const std::vector<float> input2_data = {
+ 14.16371, -9.996677, 23.359705, -5.8362885, 8.50577, 3.890133, 26.986832, 11.293919,
+ -7.2040367, -5.077221, -11.096642, 20.064266, 20.187872, -2.297474, 19.889074, -24.76117,
+ -9.60951, 25.72523, 22.055315, 20.373281, -4.083912, -1.6361217, -4.452694, 22.31394,
+ 1.7857666, -3.4938774, -0.95575714, -6.792, 24.483788, 14.758501, 8.167406, -13.673744,
+ 1.8645649, -5.4475937, 11.297581, 38.236015, -4.01342, 26.875057, 0.6700249, 39.450253,
+ -11.167023, 13.393299, -0.7329292, 10.980518, -3.8029938, -16.393318, 5.341381, -40.322437};
+
+const std::vector<bool> reference_output_data = {
+ true, true, true, false, true, true, true, true, false, false, true, true,
+ true, false, true, false, false, true, true, false, false, true, false, true,
+ true, false, true, false, true, true, false, false, false, false, true, true,
+ false, true, false, true, false, true, true, true, false, false, true, false};
+
+} // namespace less_float_with_no_broadcasting
+
+namespace less_float_with_broadcasting
+{
+
+/*
+ * Less Kernel:
+ *
+ * Input_1(2, 5) Input_2(1, 5)
+ * \ /
+ * Less(with broadcast)
+ * |
+ * Output(2, 5)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0xc0, 0x00, 0x00, 0x00, 0x14, 0x02, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xac, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x31, 0x2e, 0x31, 0x34, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xbc, 0xfe, 0xff, 0xff, 0xc0, 0xfe, 0xff, 0xff, 0xc4, 0xfe, 0xff, 0xff, 0xc8, 0xfe, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x14, 0x00, 0x00, 0x00, 0x88, 0xff, 0xff, 0xff,
+ 0x04, 0x00, 0x00, 0x00, 0x4c, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xc6, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff,
+ 0x0d, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f,
+ 0x31, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input1_data = {11.259954, 0.61867523, -7.2976017, 16.326784, -1.7243233,
+ -9.790066, -2.8924255, -1.1683407, -7.3359947, 22.979622};
+
+const std::vector<float> input2_data = {0.67757416, 10.977215, 6.6511993, -7.3085804, 8.511749};
+
+const std::vector<bool> reference_output_data = {false, true, true, false, true,
+ true, true, true, true, false};
+
+} // namespace less_float_with_broadcasting
+
+namespace neg_less_float_with_broadcasting
+{
+
+/*
+ * Less Kernel with input type mismatch:
+ *
+ * Input_1(2, 5) Input_2(1, 5)
+ * \ /
+ * Less(with broadcast)
+ * |
+ * Output(2, 5)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
+ 0x3c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa4, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input1_data = {};
+
+const std::vector<float> input2_data = {};
+
+const std::vector<bool> reference_output_data = {};
+
+} // namespace neg_less_float_with_broadcasting
+
+class TestDataFloatLess : public TestDataLessBase<float, bool>
+{
+public:
+ explicit TestDataFloatLess(bool is_with_broadcast, bool is_neg)
+ : TestDataLessBase<float, bool>(is_with_broadcast)
+ {
+ if (not is_with_broadcast)
+ {
+ if (is_neg)
+ {
+ _input1_data = neg_less_float_with_no_broadcasting::input1_data;
+ _input2_data = neg_less_float_with_no_broadcasting::input2_data;
+ _reference_output_data = neg_less_float_with_no_broadcasting::reference_output_data;
+ _test_kernel_model_circle = neg_less_float_with_no_broadcasting::test_kernel_model_circle;
+ }
+ else
+ {
+ _input1_data = less_float_with_no_broadcasting::input1_data;
+ _input2_data = less_float_with_no_broadcasting::input2_data;
+ _reference_output_data = less_float_with_no_broadcasting::reference_output_data;
+ _test_kernel_model_circle = less_float_with_no_broadcasting::test_kernel_model_circle;
+ }
+ }
+ else
+ {
+ if (is_neg)
+ {
+ _input1_data = neg_less_float_with_broadcasting::input1_data;
+ _input2_data = neg_less_float_with_broadcasting::input2_data;
+ _reference_output_data = neg_less_float_with_broadcasting::reference_output_data;
+ _test_kernel_model_circle = neg_less_float_with_broadcasting::test_kernel_model_circle;
+ }
+ else
+ {
+ _input1_data = less_float_with_broadcasting::input1_data;
+ _input2_data = less_float_with_broadcasting::input2_data;
+ _reference_output_data = less_float_with_broadcasting::reference_output_data;
+ _test_kernel_model_circle = less_float_with_broadcasting::test_kernel_model_circle;
+ }
+ }
+ }
+
+ ~TestDataFloatLess() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_LESS_KERNEL_FLOAT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/less/IntLessKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/less/IntLessKernel.h
new file mode 100644
index 000000000..750d45d67
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/less/IntLessKernel.h
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_LESS_KERNEL_INT_H
+#define LUCI_INTERPRETER_TEST_MODELS_LESS_KERNEL_INT_H
+
+#include "TestDataLessBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace less_int_with_no_broadcasting
+{
+
+/*
+ * Less Kernel:
+ *
+ * Input_1(1, 5) Input_2(1, 5)
+ * \ /
+ * Less(with broadcast)
+ * |
+ * Output(1, 5)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0xc0, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x28, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xac, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x31, 0x2e, 0x31, 0x34, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc4, 0xfe, 0xff, 0xff, 0xc8, 0xfe, 0xff, 0xff, 0xcc, 0xfe, 0xff, 0xff, 0xd0, 0xfe, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x8e, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x14, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff,
+ 0x04, 0x00, 0x00, 0x00, 0x4c, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xc2, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00,
+ 0xb4, 0xff, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x65, 0x72, 0x5f, 0x31, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x65, 0x72, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<int32_t> input1_data = {22, 31, 14, 5, 3};
+
+const std::vector<int32_t> input2_data = {3, 14, 5, 14, 5};
+
+const std::vector<bool> reference_output_data = {false, false, false, true, true};
+
+} // namespace less_int_with_no_broadcasting
+
+namespace neg_less_int_with_no_broadcasting
+{
+
+/*
+ * Less Kernel with input type mismatch:
+ *
+ * Input_1(1, 5) Input_2(1, 5)
+ * \ /
+ * Less(with broadcast)
+ * |
+ * Output(1, 5)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xac, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0xd4, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3a, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<int32_t> input1_data = {};
+
+const std::vector<int32_t> input2_data = {};
+
+const std::vector<bool> reference_output_data = {};
+
+} // namespace neg_less_int_with_no_broadcasting
+
+namespace less_int_with_broadcasting
+{
+
+/*
+ * Less Kernel:
+ *
+ * Input_1(2, 5) Input_2(1, 5)
+ * \ /
+ * Less(with broadcast)
+ * |
+ * Output(2, 5)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0xc0, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x28, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xac, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x31, 0x2e, 0x31, 0x34, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc4, 0xfe, 0xff, 0xff, 0xc8, 0xfe, 0xff, 0xff, 0xcc, 0xfe, 0xff, 0xff, 0xd0, 0xfe, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x8e, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x14, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff,
+ 0x04, 0x00, 0x00, 0x00, 0x4c, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xc2, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00,
+ 0xb4, 0xff, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x65, 0x72, 0x5f, 0x31, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x65, 0x72, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<int32_t> input1_data = {-4, 15, 4, 21, -3, 13, 5, -3, -5, 5};
+
+const std::vector<int32_t> input2_data = {5, 5, 6, 5, 6};
+
+const std::vector<bool> reference_output_data = {true, false, true, false, true,
+ false, false, true, true, true};
+
+} // namespace less_int_with_broadcasting
+
+namespace neg_less_int_with_broadcasting
+{
+
+/*
+ * Less Kernel with input type mismatch:
+ *
+ * Input_1(2, 5) Input_2(1, 5)
+ * \ /
+ * Less(with broadcast)
+ * |
+ * Output(2, 5)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xac, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0xd4, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3a, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<int32_t> input1_data = {};
+
+const std::vector<int32_t> input2_data = {};
+
+const std::vector<bool> reference_output_data = {};
+
+} // namespace neg_less_int_with_broadcasting
+
+class TestDataIntLess : public TestDataLessBase<int32_t, bool>
+{
+public:
+ explicit TestDataIntLess(bool is_with_broadcast, bool is_neg)
+ : TestDataLessBase<int32_t, bool>(is_with_broadcast)
+ {
+ if (is_with_broadcast)
+ {
+ if (is_neg)
+ {
+ _input1_data = neg_less_int_with_broadcasting::input1_data;
+ _input2_data = neg_less_int_with_broadcasting::input2_data;
+ _reference_output_data = neg_less_int_with_broadcasting::reference_output_data;
+ _test_kernel_model_circle = neg_less_int_with_broadcasting::test_kernel_model_circle;
+ }
+ else
+ {
+ _input1_data = less_int_with_broadcasting::input1_data;
+ _input2_data = less_int_with_broadcasting::input2_data;
+ _reference_output_data = less_int_with_broadcasting::reference_output_data;
+ _test_kernel_model_circle = less_int_with_broadcasting::test_kernel_model_circle;
+ }
+ }
+ else
+ {
+ if (is_neg)
+ {
+ _input1_data = neg_less_int_with_no_broadcasting::input1_data;
+ _input2_data = neg_less_int_with_no_broadcasting::input2_data;
+ _reference_output_data = neg_less_int_with_no_broadcasting::reference_output_data;
+ _test_kernel_model_circle = neg_less_int_with_no_broadcasting::test_kernel_model_circle;
+ }
+ else
+ {
+ _input1_data = less_int_with_no_broadcasting::input1_data;
+ _input2_data = less_int_with_no_broadcasting::input2_data;
+ _reference_output_data = less_int_with_no_broadcasting::reference_output_data;
+ _test_kernel_model_circle = less_int_with_no_broadcasting::test_kernel_model_circle;
+ }
+ }
+ }
+
+ ~TestDataIntLess() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_LESS_KERNEL_INT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/less/NegTestDataLessKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/less/NegTestDataLessKernel.h
new file mode 100644
index 000000000..c81212a76
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/less/NegTestDataLessKernel.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_NEG_TEST_MODELS_LESS_KERNEL_H
+#define LUCI_INTERPRETER_NEG_TEST_MODELS_LESS_KERNEL_H
+
+#include "TestDataLessBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+namespace neg_less_kernel_wrong_output
+{
+
+/*
+ * Less Kernel with wrong output type
+ *
+ * Input_1(1, 4, 4, 3) Input_2(1, 4, 4, 3)
+ * \ /
+ * Less(no broadcast)
+ * |
+ * Output(1, 4, 4, 3)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x6c, 0x01, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_less_kernel_wrong_output
+
+class NegTestDataLessKernel : public NegTestDataBase
+{
+public:
+ NegTestDataLessKernel()
+ {
+ _test_kernel_model_circle = neg_less_kernel_wrong_output::test_kernel_model_circle;
+ }
+
+ ~NegTestDataLessKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_NEG_TEST_MODELS_LESS_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/less/QuantLessKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/less/QuantLessKernel.h
new file mode 100644
index 000000000..df51e057e
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/less/QuantLessKernel.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_LESS_KERNEL_QUANT_H
+#define LUCI_INTERPRETER_TEST_MODELS_LESS_KERNEL_QUANT_H
+
+#include "TestDataLessBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace less_uint8_with_no_broadcasting
+{
+
+/*
+ * Less Kernel:
+ *
+ * Input_1(1, 4, 4, 3) Input_2(1, 4, 4, 3)
+ * \ /
+ * Less(no broadcast)
+ * |
+ * Output(1, 4, 4, 3)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x1c, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x2c, 0x02, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff,
+ 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29,
+ 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0xcc, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x8a, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+ 0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00,
+ 0x7c, 0xff, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x81, 0x80, 0x00, 0x3c, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xbf, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x54, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x81, 0x80, 0x00, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xbf, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<uint8_t> input1_data = {
+ 14, 5, 251, 243, 14, 243, 251, 5, 34, 252, 245, 252, 11, 250, 31, 14,
+ 5, 250, 21, 5, 24, 233, 5, 235, 23, 25, 15, 6, 22, 251, 23, 252,
+ 242, 5, 14, 21, 234, 242, 5, 253, 16, 244, 5, 13, 21, 5, 15, 252};
+
+const std::vector<uint8_t> input2_data = {5, 2, 5, 14, 14, 24, 15, 5, 13, 4, 5, 251,
+ 241, 14, 253, 253, 5, 254, 245, 5, 13, 40, 253, 5,
+ 253, 235, 5, 5, 252, 252, 5, 5, 5, 5, 252, 253,
+ 252, 13, 251, 251, 7, 253, 13, 5, 5, 253, 5, 5};
+
+const std::vector<bool> reference_output_data = {
+ false, false, false, false, false, false, false, false, false, false, false, false,
+ true, false, true, true, false, true, true, false, false, false, true, false,
+ true, true, false, false, true, true, false, false, false, false, true, true,
+ true, false, true, false, false, true, true, false, false, true, false, false};
+
+} // namespace less_uint8_with_no_broadcasting
+
+namespace neg_less_uint8_with_no_broadcasting
+{
+
+/*
+ * Less Kernel with input type mismatch:
+ *
+ * Input_1(1, 4, 4, 3) Input_2(1, 4, 4, 3)
+ * \ /
+ * Less(no broadcast)
+ * |
+ * Output(1, 4, 4, 3)
+ */
+
+const unsigned char test_kernel_model_circle[] = {};
+
+const std::vector<uint8_t> input1_data = {};
+
+const std::vector<uint8_t> input2_data = {};
+
+const std::vector<bool> reference_output_data = {};
+
+} // namespace neg_less_uint8_with_no_broadcasting
+
+class TestDataQuantLess : public TestDataLessBase<uint8_t, bool>
+{
+public:
+ explicit TestDataQuantLess(bool is_with_broadcast, bool is_neg)
+ : TestDataLessBase<uint8_t, bool>(is_with_broadcast)
+ {
+ if (is_with_broadcast)
+ {
+ assert(false && "Not impl yet");
+ }
+ else
+ {
+ if (is_neg)
+ {
+ _input1_data = neg_less_uint8_with_no_broadcasting::input1_data;
+ _input2_data = neg_less_uint8_with_no_broadcasting::input2_data;
+ _reference_output_data = neg_less_uint8_with_no_broadcasting::reference_output_data;
+ _test_kernel_model_circle = neg_less_uint8_with_no_broadcasting::test_kernel_model_circle;
+ }
+ else
+ {
+ _input1_data = less_uint8_with_no_broadcasting::input1_data;
+ _input2_data = less_uint8_with_no_broadcasting::input2_data;
+ _reference_output_data = less_uint8_with_no_broadcasting::reference_output_data;
+ _test_kernel_model_circle = less_uint8_with_no_broadcasting::test_kernel_model_circle;
+ }
+ }
+ }
+
+ ~TestDataQuantLess() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_LESS_KERNEL_QUANT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/less/TestDataLessBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/less/TestDataLessBase.h
new file mode 100644
index 000000000..1264ab301
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/less/TestDataLessBase.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_LESS_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_LESS_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T, typename U> class TestDataLessBase : public TestDataBase<T, U>
+{
+public:
+ explicit TestDataLessBase(bool)
+ {
+ // Do nothing
+ }
+
+ TestDataLessBase() = delete;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input1_data;
+ case 1:
+ return _input2_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<U> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input1_data;
+ std::vector<T> _input2_data;
+ std::vector<U> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_LESS_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/less_equal/FloatLessEqualKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/less_equal/FloatLessEqualKernel.h
new file mode 100644
index 000000000..c20966d83
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/less_equal/FloatLessEqualKernel.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_LESS_EQUAL_KERNEL_FLOAT_H
+#define LUCI_INTERPRETER_TEST_MODELS_LESS_EQUAL_KERNEL_FLOAT_H
+
+#include "TestDataLessEqualBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace less_equal_float
+{
+
+/*
+ * LessEqual Kernel:
+ *
+ * Input_1(1, 4, 4, 3) Input_2(1, 4, 4, 3)
+ * \ /
+ * LessEqual(no broadcast)
+ * |
+ * Output(1, 4, 4, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input1_data = {
+ -0.01787583, -0.8314556, -0.47624078, -1.9747407, -0.51676583, -0.20183715, -1.9358647,
+ 0.7616414, -0.0899037, 2.048367, -1.3174965, 1.5267943, 0.68707687, 1.3464743,
+ 0.98674047, -1.4853697, 1.9973947, 0.5170953, 0.37471953, -1.6011852, 0.32045737,
+ -0.6598305, -1.7946662, 1.2349467, 1.3320708, 0.5151753, 1.345111, -0.16560331,
+ 0.82792366, -1.734876, 0.043626763, -0.0118546495, 0.31535238, 0.1888555, -0.32523626,
+ -0.997665, 0.5819472, -2.3194845, -1.6897905, 0.9981752, -1.2897044, 0.75768864,
+ 0.56781554, -1.0565805, -1.4891449, 0.2493645, -1.1312587, 0.6837854};
+
+const std::vector<float> input2_data = {
+ 0.30809638, -0.28285328, -0.8437058, 1.7689779, 0.5182942, 0.571205, -0.89484423,
+ 0.28100377, 0.5453497, 1.3848042, -0.04359268, -1.7448778, -0.5375435, -0.85059136,
+ -0.77961826, -0.4916915, 1.3359088, -0.09580261, 0.6158275, -0.05056348, 0.90505254,
+ 0.94226706, 1.136139, -0.45077038, -0.5018571, -1.1543767, 0.85094684, -0.13731039,
+ -0.3298641, 0.9474698, -0.48497504, -0.14864737, -0.009302358, -1.1259161, 0.44226727,
+ 1.0149708, 0.36024934, 0.4969523, 0.45014778, -0.34718898, 1.2260172, 0.35304692,
+ -1.3037513, -0.2565706, 0.18085766, -0.7099202, -0.9203537, -1.2257448};
+
+const std::vector<bool> reference_output_data = {
+ true, true, false, true, true, true, true, false, true, false, true, false,
+ false, false, false, true, false, false, true, true, true, true, true, false,
+ false, false, false, true, false, true, false, false, false, false, true, true,
+ false, true, true, false, true, false, false, true, true, false, true, false};
+
+} // namespace less_equal_float
+
+namespace neg_less_equal_float_with_no_broadcasting
+{
+
+/*
+ * LessEqual Kernel with input type mismatch:
+ *
+ * Input_1(1, 4, 4, 3)-float Input_2(1, 4, 4, 3)-int
+ * \ /
+ * LessEqual(no broadcast)
+ * |
+ * Output(1, 4, 4, 3)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3f, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input1_data = {};
+
+const std::vector<float> input2_data = {};
+
+const std::vector<bool> reference_output_data = {};
+
+} // namespace neg_less_equal_float_with_no_broadcasting
+
+class TestDataFloatLessEqual : public TestDataLessEqualBase<float, bool>
+{
+public:
+ explicit TestDataFloatLessEqual(bool is_with_broadcast, bool is_neg)
+ : TestDataLessEqualBase<float, bool>(is_with_broadcast)
+ {
+ if (is_with_broadcast)
+ {
+ assert(false && "Not impl yet");
+ }
+ else
+ {
+ if (is_neg)
+ {
+ _input1_data = neg_less_equal_float_with_no_broadcasting::input1_data;
+ _input2_data = neg_less_equal_float_with_no_broadcasting::input2_data;
+ _reference_output_data = neg_less_equal_float_with_no_broadcasting::reference_output_data;
+ _test_kernel_model_circle =
+ neg_less_equal_float_with_no_broadcasting::test_kernel_model_circle;
+ }
+ else
+ {
+ _input1_data = less_equal_float::input1_data;
+ _input2_data = less_equal_float::input2_data;
+ _reference_output_data = less_equal_float::reference_output_data;
+ _test_kernel_model_circle = less_equal_float::test_kernel_model_circle;
+ }
+ }
+ }
+
+ ~TestDataFloatLessEqual() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_LESS_KERNEL_FLOAT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/less_equal/TestDataLessEqualBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/less_equal/TestDataLessEqualBase.h
new file mode 100644
index 000000000..460773710
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/less_equal/TestDataLessEqualBase.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_LESS_EQUAL_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_LESS_EQUAL_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T, typename U> class TestDataLessEqualBase : public TestDataBase<T, U>
+{
+public:
+ explicit TestDataLessEqualBase(bool)
+ {
+ // Do nothing
+ }
+
+ TestDataLessEqualBase() = delete;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input1_data;
+ case 1:
+ return _input2_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<U> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input1_data;
+ std::vector<T> _input2_data;
+ std::vector<U> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_LESS_EQUAL_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_and/BoolLogicalAndKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_and/BoolLogicalAndKernel.h
new file mode 100644
index 000000000..8b87fa28e
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_and/BoolLogicalAndKernel.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_BOOL_LOGICAL_AND_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_BOOL_LOGICAL_AND_KERNEL_H
+
+#include "TestDataLogicalAndBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace logical_and_bool
+{
+/*
+ * LogicalAnd Kernel:
+ *
+ * Input(1, 4, 4, 3) Input(1, 4, 4, 3)
+ * | |
+ * LogicalAnd
+ * |
+ * Output(1, 4, 4, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9c, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xcc, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<bool> input1_data = {
+ true, false, true, true, true, false, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true, true, true, false, false};
+const std::vector<bool> input2_data = {
+ true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false};
+
+const std::vector<bool> reference_output_data = {
+ true, false, true, true, true, false, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true, true, false, false, false};
+
+} // namespace logical_and_bool
+
+class TestDataBoolLogicalAnd : public TestDataLogicalAndBase<bool>
+{
+public:
+ TestDataBoolLogicalAnd()
+ {
+ _input1_data = logical_and_bool::input1_data;
+ _input2_data = logical_and_bool::input2_data;
+ _reference_output_data = logical_and_bool::reference_output_data;
+ _test_kernel_model_circle = logical_and_bool::test_kernel_model_circle;
+ }
+
+ ~TestDataBoolLogicalAnd() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_LOGICAL_AND_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_and/NegLogicalAndKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_and/NegLogicalAndKernel.h
new file mode 100644
index 000000000..6624fe2a2
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_and/NegLogicalAndKernel.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_LOGICAL_AND_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_LOGICAL_AND_KERNEL_H
+
+#include "TestDataLogicalAndBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_logical_and_inputs_type_mismatch
+{
+/*
+ * LogicalAnd Kernel with input types mismatch:
+ *
+ * Input(1, 4, 4, 3)-Bool Input(1, 4, 4, 3)-Float32
+ * | |
+ * LogicalAnd
+ * |
+ * Output(1, 4, 4, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x94, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x56, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+} // namespace neg_logical_and_inputs_type_mismatch
+
+class NegTestDataInputTypeMismatchLogicalAndKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInputTypeMismatchLogicalAndKernel()
+ {
+ _test_kernel_model_circle = neg_logical_and_inputs_type_mismatch::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInputTypeMismatchLogicalAndKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_LOGICAL_AND_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_and/TestDataLogicalAndBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_and/TestDataLogicalAndBase.h
new file mode 100644
index 000000000..c2842a333
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_and/TestDataLogicalAndBase.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_LOGICAL_AND_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_LOGICAL_AND_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataLogicalAndBase : public TestDataBase<T>
+{
+public:
+ TestDataLogicalAndBase() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input1_data;
+ case 1:
+ return _input2_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input1_data;
+ std::vector<T> _input2_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_LOGICAL_AND_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_or/BoolLogicalOrKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_or/BoolLogicalOrKernel.h
new file mode 100644
index 000000000..90b7511db
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_or/BoolLogicalOrKernel.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_BOOL_LOGICAL_OR_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_BOOL_LOGICAL_OR_KERNEL_H
+
+#include "TestDataLogicalOrBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace logical_or_bool
+{
+/*
+ * LogicalOr Kernel:
+ *
+ * Input(1, 4, 4, 3) Input(1, 4, 4, 3)
+ * | |
+ * LogicalOr
+ * |
+ * Output(1, 4, 4, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9c, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xcc, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<bool> input1_data = {
+ true, false, true, true, true, false, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true, true, true, false, false};
+const std::vector<bool> input2_data = {
+ true, false, true, true, true, true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true, true, true, true, true,
+ true, false, true, true, true, true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true, true, false, false, false};
+
+const std::vector<bool> reference_output_data = {
+ true, false, true, true, true, true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true, true, true, false, false};
+
+} // namespace logical_or_bool
+
+class TestDataBoolLogicalOr : public TestDataLogicalOrBase<bool>
+{
+public:
+ TestDataBoolLogicalOr()
+ {
+ _input1_data = logical_or_bool::input1_data;
+ _input2_data = logical_or_bool::input2_data;
+ _reference_output_data = logical_or_bool::reference_output_data;
+ _test_kernel_model_circle = logical_or_bool::test_kernel_model_circle;
+ }
+
+ ~TestDataBoolLogicalOr() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_LOGICAL_OR_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_or/NegLogicalOrKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_or/NegLogicalOrKernel.h
new file mode 100644
index 000000000..1225d98fb
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_or/NegLogicalOrKernel.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_LOGICAL_OR_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_LOGICAL_OR_KERNEL_H
+
+#include "TestDataLogicalOrBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_logical_or_inputs_type_mismatch
+{
+/*
+ * LogicalOr Kernel with input types mismatch:
+ *
+ * Input(1, 4, 4, 3)-Bool Input(1, 4, 4, 3)-Float32
+ * | |
+ * LogicalOr
+ * |
+ * Output(1, 4, 4, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x94, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x54, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+} // namespace neg_logical_or_inputs_type_mismatch
+
+class NegTestDataInputTypeMismatchLogicalOrKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInputTypeMismatchLogicalOrKernel()
+ {
+ _test_kernel_model_circle = neg_logical_or_inputs_type_mismatch::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInputTypeMismatchLogicalOrKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_LOGICAL_OR_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_or/TestDataLogicalOrBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_or/TestDataLogicalOrBase.h
new file mode 100644
index 000000000..af9fee2ad
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_or/TestDataLogicalOrBase.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_LOGICAL_OR_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_LOGICAL_OR_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataLogicalOrBase : public TestDataBase<T>
+{
+public:
+ TestDataLogicalOrBase() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input1_data;
+ case 1:
+ return _input2_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input1_data;
+ std::vector<T> _input2_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_LOGICAL_OR_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logistic/FloatLogisticKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logistic/FloatLogisticKernel.h
new file mode 100644
index 000000000..23f9f7b8b
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logistic/FloatLogisticKernel.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_FLOAT_LOGISTIC_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_LOGISTIC_KERNEL_H
+
+#include "TestDataLogisticBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace logistic_float
+{
+/*
+ * Logistic Kernel:
+ *
+ * Input(1, 3, 3, 2)
+ * |
+ * Logistic
+ * |
+ * Output(1, 3, 3, 2)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff,
+ 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {29.353455, 12.060211, 11.372606, -9.009369, 3.0267563,
+ 5.1447716, 21.289762, 19.976126, 8.726238, 4.8797092,
+ 3.64571, 34.80062, -6.9072685, -2.2714958, -16.44065,
+ 0.334301, -20.372694, 4.1522675};
+
+const std::vector<float> reference_output_data = {
+ 1.0, 0.99999416, 0.99998844, 0.00012225899, 0.9537683, 0.994204,
+ 1.0, 1.0, 0.99983776, 0.9924581, 0.97456115, 1.0,
+ 0.0009994869, 0.093511336, 7.2429586e-08, 0.5828055, 1.4198792e-09, 0.98451483};
+
+} // namespace logistic_float
+
+class TestDataFloatLogistic : public TestDataLogisticBase<float>
+{
+public:
+ TestDataFloatLogistic()
+ {
+ _input_data = logistic_float::input_data;
+ _reference_output_data = logistic_float::reference_output_data;
+ _test_kernel_model_circle = logistic_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatLogistic() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_LOGISTIC_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logistic/NegLogisticKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logistic/NegLogisticKernel.h
new file mode 100644
index 000000000..fec9689ba
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logistic/NegLogisticKernel.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_LOGISTIC_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_LOGISTIC_KERNEL_H
+
+#include "TestDataLogisticBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_logistic_input_output_type_mismatch
+{
+/*
+ * Logistic Kernel with input output type mismatch (should be equal):
+ *
+ * Input(1, 3, 3, 2) - Float
+ * |
+ * Logistic
+ * |
+ * Output(1, 3, 3, 2) - Int
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff,
+ 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+} // namespace neg_logistic_input_output_type_mismatch
+
+namespace neg_logistic_no_quant_params
+{
+/*
+ * Logistic Kernel with UINT8 type and without quant params:
+ *
+ * Input(1, 3, 3, 2) - UINT8
+ * |
+ * Logistic (no quant params)
+ * |
+ * Output(1, 3, 3, 2) - UINT8
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff,
+ 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+} // namespace neg_logistic_no_quant_params
+
+class NegTestDataInputOutputTypeMismatchLogisticKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInputOutputTypeMismatchLogisticKernel()
+ {
+ _test_kernel_model_circle = neg_logistic_input_output_type_mismatch::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInputOutputTypeMismatchLogisticKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataNoQuantParamsLogisticKernel : public NegTestDataBase
+{
+public:
+ NegTestDataNoQuantParamsLogisticKernel()
+ {
+ _test_kernel_model_circle = neg_logistic_no_quant_params::test_kernel_model_circle;
+ }
+
+ ~NegTestDataNoQuantParamsLogisticKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_LOGISTIC_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logistic/TestDataLogisticBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logistic/TestDataLogisticBase.h
new file mode 100644
index 000000000..faffd2f76
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logistic/TestDataLogisticBase.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_LOGISTIC_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_LOGISTIC_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataLogisticBase : public TestDataBase<T>
+{
+public:
+ TestDataLogisticBase() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_LOGISTIC_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/maxpool2d/FloatMaxPool2DKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/maxpool2d/FloatMaxPool2DKernel.h
new file mode 100644
index 000000000..927859fd2
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/maxpool2d/FloatMaxPool2DKernel.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_FLOAT_MAXPOOL2D_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_MAXPOOL2D_KERNEL_H
+
+#include "TestDataMaxPool2DBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace maxpool2d_float
+{
+/*
+ * maxpool2d Kernel:
+ *
+ * Input(1, 3, 5, 1)
+ * |
+ * MaxPool2D
+ * |
+ * Output(1, 2, 2, 1)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0xbc, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x2c, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0xa8, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x96, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x08, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x08, 0x00,
+ 0x00, 0x00, 0x07, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x39, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x31, 0x2e, 0x35, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xd0, 0xfe, 0xff, 0xff, 0xd4, 0xfe, 0xff, 0xff, 0xd8, 0xfe, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x1c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x17, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x5c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xba, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xac, 0xff, 0xff, 0xff,
+ 0x11, 0x00, 0x00, 0x00, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x43,
+ 0x61, 0x6c, 0x6c, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x73, 0x65, 0x72, 0x76,
+ 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x78, 0x3a, 0x30, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {
+ 1, -1, 0, -2, 2, //
+ -7, -6, -5, -4, -3, //
+ 5, 4, 3, 6, 7, //
+};
+
+const std::vector<float> reference_output_data{
+ 1, 2, //
+ 5, 7, //
+};
+
+} // namespace maxpool2d_float
+
+class TestDataFloatMaxPool2D : public TestDataMaxPool2DBase<float>
+{
+public:
+ TestDataFloatMaxPool2D()
+ {
+ _input_data = maxpool2d_float::input_data;
+ _reference_output_data = maxpool2d_float::reference_output_data;
+ _test_kernel_model_circle = maxpool2d_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatMaxPool2D() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_MAXPOOL2D_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/maxpool2d/NegMaxPool2DKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/maxpool2d/NegMaxPool2DKernel.h
new file mode 100644
index 000000000..dbba73663
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/maxpool2d/NegMaxPool2DKernel.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_MAXPOOL2D_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_MAXPOOL2D_KERNEL_H
+
+#include "TestDataMaxPool2DBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_maxpool2d_kernel
+{
+/*
+ * maxpool2d Kernel with input_type != output_type:
+ *
+ * Input(1, 8, 8, 1) = Float32
+ * |
+ * MaxPool2D
+ * |
+ * Output(1, 7, 7, 1) = Int32
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x58, 0x01, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff,
+ 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x1c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x17, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x50, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_maxpool2d_kernel
+
+namespace neg_invalid_input_shape_maxpool2d_kernel
+{
+/*
+ * maxpool2d Kernel with invalid input shape rank=5 (should be == 4):
+ *
+ * Input(1, 1, 8, 8, 1) = Int32
+ * |
+ * MaxPool2D
+ * |
+ * Output(1, 7, 7, 1) = Int32
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff,
+ 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x1c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x17, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_invalid_input_shape_maxpool2d_kernel
+
+namespace neg_no_quant_params_maxpool2d_kernel
+{
+/*
+ * maxpool2d Kernel S16 without quant params:
+ *
+ * Input(1, 1, 8, 8, 1) = INT16
+ * |
+ * MaxPool2D (no quant params)
+ * |
+ * Output(1, 7, 7, 1) = INT16
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x6c, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff,
+ 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x1c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x17, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_no_quant_params_maxpool2d_kernel
+
+class NegTestDataInputOutputTypeMismatchMaxPool2DKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInputOutputTypeMismatchMaxPool2DKernel()
+ {
+ _test_kernel_model_circle = neg_maxpool2d_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInputOutputTypeMismatchMaxPool2DKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInvalidInputShapeMaxPool2DKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInvalidInputShapeMaxPool2DKernel()
+ {
+ _test_kernel_model_circle = neg_invalid_input_shape_maxpool2d_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInvalidInputShapeMaxPool2DKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataNoQuantParamsMaxPool2DKernel : public NegTestDataBase
+{
+public:
+ NegTestDataNoQuantParamsMaxPool2DKernel()
+ {
+ _test_kernel_model_circle = neg_no_quant_params_maxpool2d_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataNoQuantParamsMaxPool2DKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_MAXPOOL2D_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/maxpool2d/TestDataMaxPool2DBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/maxpool2d/TestDataMaxPool2DBase.h
new file mode 100644
index 000000000..71a81cefa
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/maxpool2d/TestDataMaxPool2DBase.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_MAXPOOL2D_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_MAXPOOL2D_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataMaxPool2DBase : public TestDataBase<T>
+{
+public:
+ TestDataMaxPool2DBase() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_MAXPOOL2D_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/mul/FloatMulKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/mul/FloatMulKernel.h
new file mode 100644
index 000000000..444bb534b
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/mul/FloatMulKernel.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_MUL_KERNEL_FLOAT_H
+#define LUCI_INTERPRETER_TEST_MODELS_MUL_KERNEL_FLOAT_H
+
+#include "TestDataMulBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace mul_float_with_broadcasting
+{
+
+/*
+ * Mul Kernel:
+ *
+ * Input_1(2, 5) Input_2(2, 1)
+ * \ /
+ * Mul(with broadcast)
+ * |
+ * Output(2, 5)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0xc0, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x28, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xac, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x31, 0x2e, 0x35, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc4, 0xfe, 0xff, 0xff, 0xc8, 0xfe, 0xff, 0xff, 0xcc, 0xfe, 0xff, 0xff, 0xd0, 0xfe, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3c, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00,
+ 0x4d, 0x75, 0x6c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0xc6, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63,
+ 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f, 0x31, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x10, 0x00,
+ 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x65, 0x72, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input1_data = {-16.302355, -4.020832, -7.797722, -10.514711, -13.203278,
+ -4.742243, 14.114815, 13.727003, 7.3895016, -2.0813313};
+const std::vector<float> input2_data = {-3.132759, 9.31464};
+const std::vector<float> reference_output_data = {51.07135, 12.596298, 24.428385, 32.940056,
+ 41.362686, -44.172283, 131.47443, 127.86209,
+ 68.83054, -19.386852};
+
+} // namespace mul_float_with_broadcasting
+
+namespace mul_float_no_broadcasting
+{
+/*
+ * Mul Kernel:
+ *
+ * Input_1(2, 5) Input_2(2, 5)
+ * \ /
+ * Mul(no broadcast)
+ * |
+ * Output(2, 5)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0xc0, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x28, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xac, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x31, 0x2e, 0x35, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc4, 0xfe, 0xff, 0xff, 0xc8, 0xfe, 0xff, 0xff, 0xcc, 0xfe, 0xff, 0xff, 0xd0, 0xfe, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3c, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00,
+ 0x4d, 0x75, 0x6c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0xc6, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63,
+ 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f, 0x31, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x10, 0x00,
+ 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x65, 0x72, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+std::vector<float> input1_data = {18.033651, -15.601158, 3.842373, 17.90259, -12.840965,
+ 19.272898, 22.070192, 12.965511, 23.20587, -7.0852413};
+std::vector<float> input2_data = {20.24965, 4.263008, 16.145443, 25.501696, -8.905457,
+ -2.0830078, 28.85225, 24.545036, -13.7073345, 9.774281};
+std::vector<float> reference_output_data = {365.1751, -66.507866, 62.03681, 456.5464,
+ 114.35466, -40.145596, 636.77466, 318.23895,
+ -318.0906, -69.253136};
+
+} // namespace mul_float_no_broadcasting
+
+class TestDataFloatMul : public TestDataMulBase<float>
+{
+public:
+ explicit TestDataFloatMul(bool is_with_broadcast) : TestDataMulBase<float>(is_with_broadcast)
+ {
+ if (is_with_broadcast)
+ {
+ _input1_data = mul_float_with_broadcasting::input1_data;
+ _input2_data = mul_float_with_broadcasting::input2_data;
+ _reference_output_data = mul_float_with_broadcasting::reference_output_data;
+ _test_kernel_model_circle = mul_float_with_broadcasting::test_kernel_model_circle;
+ }
+ else
+ {
+ _input1_data = mul_float_no_broadcasting::input1_data;
+ _input2_data = mul_float_no_broadcasting::input2_data;
+ _reference_output_data = mul_float_no_broadcasting::reference_output_data;
+ _test_kernel_model_circle = mul_float_no_broadcasting::test_kernel_model_circle;
+ }
+ }
+
+ ~TestDataFloatMul() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_MUL_KERNEL_FLOAT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/mul/IntMulKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/mul/IntMulKernel.h
new file mode 100644
index 000000000..7dc1c538b
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/mul/IntMulKernel.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_MUL_KERNEL_INT_H
+#define LUCI_INTERPRETER_TEST_MODELS_MUL_KERNEL_INT_H
+
+#include "TestDataMulBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace mul_int_with_broadcasting
+{
+
+/*
+ * Mul Kernel:
+ *
+ * Input_1(2, 5) Input_2(2, 1)
+ * \ /
+ * Mul(with broadcast)
+ * |
+ * Output(2, 5)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0xc0, 0x00, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00, 0x34, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xac, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x31, 0x2e, 0x35, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xb8, 0xfe, 0xff, 0xff, 0xbc, 0xfe, 0xff, 0xff, 0xc0, 0xfe, 0xff, 0xff, 0xc4, 0xfe, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x84, 0xff, 0xff, 0xff,
+ 0x03, 0x00, 0x00, 0x00, 0x4d, 0x75, 0x6c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0xc2, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0xb4, 0xff, 0xff, 0xff,
+ 0x0d, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f,
+ 0x31, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<int32_t> input1_data = {-5, 5, 5, -4, -4, 15, -13, 23, 5, 5};
+const std::vector<int32_t> input2_data = {-2, 14};
+const std::vector<int32_t> reference_output_data = {10, -10, -10, 8, 8, 210, -182, 322, 70, 70};
+
+} // namespace mul_int_with_broadcasting
+
+namespace mul_int_no_broadcasting
+{
+/*
+ * Mul Kernel:
+ *
+ * Input_1(2, 5) Input_2(2, 5)
+ * \ /
+ * Mul(no broadcast)
+ * |
+ * Output(2, 5)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0xc0, 0x00, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00, 0x34, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xac, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x31, 0x2e, 0x35, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xb8, 0xfe, 0xff, 0xff, 0xbc, 0xfe, 0xff, 0xff, 0xc0, 0xfe, 0xff, 0xff, 0xc4, 0xfe, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x84, 0xff, 0xff, 0xff,
+ 0x03, 0x00, 0x00, 0x00, 0x4d, 0x75, 0x6c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0xc2, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0xb4, 0xff, 0xff, 0xff,
+ 0x0d, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f,
+ 0x31, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+std::vector<int32_t> input1_data = {5, 3, -3, 5, 14, 14, -3, 33, -11, 24};
+std::vector<int32_t> input2_data = {5, -3, 5, 5, 25, 5, -4, -2, 5, 25};
+std::vector<int32_t> reference_output_data = {25, -9, -15, 25, 350, 70, 12, -66, -55, 600};
+
+} // namespace mul_int_no_broadcasting
+
+class TestDataIntMul : public TestDataMulBase<int32_t>
+{
+public:
+ explicit TestDataIntMul(bool is_with_broadcast) : TestDataMulBase<int32_t>(is_with_broadcast)
+ {
+ if (is_with_broadcast)
+ {
+ _input1_data = mul_int_with_broadcasting::input1_data;
+ _input2_data = mul_int_with_broadcasting::input2_data;
+ _reference_output_data = mul_int_with_broadcasting::reference_output_data;
+ _test_kernel_model_circle = mul_int_with_broadcasting::test_kernel_model_circle;
+ }
+ else
+ {
+ _input1_data = mul_int_no_broadcasting::input1_data;
+ _input2_data = mul_int_no_broadcasting::input2_data;
+ _reference_output_data = mul_int_no_broadcasting::reference_output_data;
+ _test_kernel_model_circle = mul_int_no_broadcasting::test_kernel_model_circle;
+ }
+ }
+
+ ~TestDataIntMul() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_MUL_KERNEL_INT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/mul/NegMulKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/mul/NegMulKernel.h
new file mode 100644
index 000000000..cbbdbdd6e
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/mul/NegMulKernel.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_MUL_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_MUL_KERNEL_H
+
+#include "TestDataMulBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace input_1_wrong_type
+{
+
+/*
+ * Mul Kernel with input type mismatch:
+ *
+ * Input_1(2, 5) - Int32 Input_2(2, 1) - Float
+ * \ /
+ * Mul(with broadcast)
+ * |
+ * Output(2, 5)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xdc, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+} // namespace input_1_wrong_type
+
+namespace input_2_wrong_type
+{
+
+/*
+ * Mul Kernel with input type mismatch:
+ *
+ * Input_1(2, 5)- Float Input_2(2, 1) - Int32
+ * \ /
+ * Mul(with broadcast)
+ * |
+ * Output(2, 5)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+} // namespace input_2_wrong_type
+
+namespace unsupported_type
+{
+
+/*
+ * Mul Kernel with unsupported type:
+ *
+ * Input_1(2, 5)- Int16 Input_2(2, 1) - Int16
+ * \ /
+ * Mul(with broadcast)
+ * |
+ * Output(2, 5) - Int16
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xac, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0xd4, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x12, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+} // namespace unsupported_type
+
+class NegTestDataInput1WrongTypeMul : public NegTestDataBase
+{
+public:
+ NegTestDataInput1WrongTypeMul()
+ {
+ _test_kernel_model_circle = input_1_wrong_type::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInput1WrongTypeMul() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInput2WrongTypeMul : public NegTestDataBase
+{
+public:
+ NegTestDataInput2WrongTypeMul()
+ {
+ _test_kernel_model_circle = input_2_wrong_type::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInput2WrongTypeMul() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInt16TypeMul : public NegTestDataBase
+{
+public:
+ NegTestDataInt16TypeMul()
+ {
+ _test_kernel_model_circle = unsupported_type::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInt16TypeMul() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_MUL_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/mul/TestDataMulBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/mul/TestDataMulBase.h
new file mode 100644
index 000000000..1b64982eb
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/mul/TestDataMulBase.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_MUL_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_MUL_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataMulBase : public TestDataBase<T>
+{
+public:
+ explicit TestDataMulBase(bool)
+ {
+ // Do nothing
+ }
+
+ TestDataMulBase() = delete;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input1_data;
+ case 1:
+ return _input2_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input1_data;
+ std::vector<T> _input2_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_MUL_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/neg/FloatNegKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/neg/FloatNegKernel.h
new file mode 100644
index 000000000..3e3566648
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/neg/FloatNegKernel.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_FLOAT_NEG_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_NEG_KERNEL_H
+
+#include "TestDataNegBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_float
+{
+/*
+ * Neg Kernel:
+ *
+ * Input(1, 3, 3, 2)
+ * |
+ * Neg
+ * |
+ * Output(1, 3, 3, 2)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff,
+ 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x2a, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {-2.3082886, 5.8998604, 7.297842, 30.999863, 15.692827,
+ -18.824865, 22.614136, 5.7466774, 6.65571, -1.1786385,
+ 3.8724442, 9.483013, 19.376131, -6.1562176, -5.4431114,
+ 9.304043, 22.674402, -2.3587227};
+
+const std::vector<float> reference_output_data = {
+ 2.3082886, -5.8998604, -7.297842, -30.999863, -15.692827, 18.824865,
+ -22.614136, -5.7466774, -6.65571, 1.1786385, -3.8724442, -9.483013,
+ -19.376131, 6.1562176, 5.4431114, -9.304043, -22.674402, 2.3587227};
+
+} // namespace neg_float
+
+class TestDataFloatNeg : public TestDataNegBase<float>
+{
+public:
+ TestDataFloatNeg()
+ {
+ _input_data = neg_float::input_data;
+ _reference_output_data = neg_float::reference_output_data;
+ _test_kernel_model_circle = neg_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatNeg() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_NEG_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/neg/NegNegKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/neg/NegNegKernel.h
new file mode 100644
index 000000000..43f9c0996
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/neg/NegNegKernel.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_NEG_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_NEG_KERNEL_H
+
+#include "TestDataNegBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_neg_kernel
+{
+/*
+ * Negate Kernel with input output type mismatch (should be equal):
+ *
+ * Input(1, 3, 3, 2) - Float
+ * |
+ * Negate
+ * |
+ * Output(1, 3, 3, 2) - Int
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff,
+ 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x2a, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x54, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x3b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+} // namespace neg_input_output_type_mismatch_neg_kernel
+
+namespace neg_invalid_input_shape_neg_kernel
+{
+/*
+ * Nagate Kernel with invalid input shape rank=5 (should be == 4):
+ *
+ * Input(1, 1, 8, 8, 1) = Float32
+ * |
+ * Negate
+ * |
+ * Output(1, 7, 7, 1) = Float32
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff,
+ 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x2a, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_invalid_input_shape_neg_kernel
+
+class NegTestDataInputOutputTypeMismatchNegKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInputOutputTypeMismatchNegKernel()
+ {
+ _test_kernel_model_circle = neg_input_output_type_mismatch_neg_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInputOutputTypeMismatchNegKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInvalidInputShapeNegKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInvalidInputShapeNegKernel()
+ {
+ _test_kernel_model_circle = neg_invalid_input_shape_neg_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInvalidInputShapeNegKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_NEG_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/neg/TestDataNegBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/neg/TestDataNegBase.h
new file mode 100644
index 000000000..fcb5704ab
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/neg/TestDataNegBase.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataNegBase : public TestDataBase<T>
+{
+public:
+ TestDataNegBase() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/notequal/FloatNotEqualKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/notequal/FloatNotEqualKernel.h
new file mode 100644
index 000000000..51fd85d75
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/notequal/FloatNotEqualKernel.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NOT_EQUAL_KERNEL_FLOAT_H
+#define LUCI_INTERPRETER_TEST_MODELS_NOT_EQUAL_KERNEL_FLOAT_H
+
+#include "TestDataNotEqualBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace not_equal_float
+{
+
+/*
+ * NotEqual Kernel:
+ *
+ * Input_1(1, 4, 4, 3) Input_2(1, 4, 4, 3)
+ * \ /
+ * NotEqual(no broadcast)
+ * |
+ * Output(1, 4, 4, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input1_data = {
+ -0.01787583, -0.8314556, -0.47624078, -1.9747407, -0.51676583, -0.20183715, -1.9358647,
+ 0.7616414, -0.0899037, 2.048367, -1.3174965, 1.5267943, 0.68707687, 1.3464743,
+ 0.98674047, -1.4853697, 1.9973947, 0.5170953, 0.37471953, -1.6011852, 0.32045737,
+ -0.6598305, -1.7946662, 1.2349467, 1.3320708, 0.5151753, 1.345111, -0.16560331,
+ 0.82792366, -1.734876, 0.043626763, -0.0118546495, 0.31535238, 0.1888555, -0.32523626,
+ -0.997665, 0.5819472, -2.3194845, -1.6897905, 0.9981752, -1.2897044, 0.75768864,
+ 0.56781554, -1.0565805, -1.4891449, 0.2493645, -1.1312587, 0.6837854};
+
+const std::vector<float> input2_data = {
+ 0.30809638, -0.28285328, -0.8437058, 1.7689779, 0.5182942, 0.571205, -0.89484423,
+ 0.28100377, 0.5453497, 1.3848042, -0.04359268, -1.7448778, -0.5375435, -0.85059136,
+ -0.77961826, -0.4916915, 1.3359088, -0.09580261, 0.6158275, -0.05056348, 0.90505254,
+ 0.94226706, 1.136139, -0.45077038, -0.5018571, -1.1543767, 0.85094684, -0.13731039,
+ -0.3298641, 0.9474698, -0.48497504, -0.14864737, -0.009302358, -1.1259161, 0.44226727,
+ 1.0149708, 0.36024934, 0.4969523, 0.45014778, -0.34718898, 1.2260172, 0.35304692,
+ -1.3037513, -0.2565706, 0.18085766, -0.7099202, -0.9203537, -1.2257448};
+
+const std::vector<bool> reference_output_data = {
+ true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true};
+
+} // namespace not_equal_float
+
+namespace neg_not_equal_float_with_no_broadcasting
+{
+
+/*
+ * NotEqual Kernel with input type mismatch:
+ *
+ * Input_1(1, 4, 4, 3)-float Input_2(1, 4, 4, 3)-int
+ * \ /
+ * NotEqual(no broadcast)
+ * |
+ * Output(1, 4, 4, 3)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input1_data = {};
+
+const std::vector<float> input2_data = {};
+
+const std::vector<bool> reference_output_data = {};
+
+} // namespace neg_not_equal_float_with_no_broadcasting
+
+class TestDataFloatNotEqual : public TestDataNotEqualBase<float, bool>
+{
+public:
+ explicit TestDataFloatNotEqual(bool is_with_broadcast, bool is_neg)
+ : TestDataNotEqualBase<float, bool>(is_with_broadcast)
+ {
+ if (is_with_broadcast)
+ {
+ assert(false && "Not impl yet");
+ }
+ else
+ {
+ if (is_neg)
+ {
+ _input1_data = neg_not_equal_float_with_no_broadcasting::input1_data;
+ _input2_data = neg_not_equal_float_with_no_broadcasting::input2_data;
+ _reference_output_data = neg_not_equal_float_with_no_broadcasting::reference_output_data;
+ _test_kernel_model_circle =
+ neg_not_equal_float_with_no_broadcasting::test_kernel_model_circle;
+ }
+ else
+ {
+ _input1_data = not_equal_float::input1_data;
+ _input2_data = not_equal_float::input2_data;
+ _reference_output_data = not_equal_float::reference_output_data;
+ _test_kernel_model_circle = not_equal_float::test_kernel_model_circle;
+ }
+ }
+ }
+
+ ~TestDataFloatNotEqual() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NOT_EQUAL_KERNEL_FLOAT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/notequal/TestDataNotEqualBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/notequal/TestDataNotEqualBase.h
new file mode 100644
index 000000000..786be2170
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/notequal/TestDataNotEqualBase.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NOT_EQUAL_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_NOT_EQUAL_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T, typename U> class TestDataNotEqualBase : public TestDataBase<T, U>
+{
+public:
+ explicit TestDataNotEqualBase(bool)
+ {
+ // Do nothing
+ }
+
+ TestDataNotEqualBase() = delete;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input1_data;
+ case 1:
+ return _input2_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<U> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input1_data;
+ std::vector<T> _input2_data;
+ std::vector<U> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NOT_EQUAL_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/pack/PackKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/pack/PackKernel.h
new file mode 100644
index 000000000..22d9f666d
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/pack/PackKernel.h
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_PACK_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_PACK_KERNEL_H
+
+#include "TestDataPackBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace pack_float
+{
+/*
+ * Pack Kernel:
+ *
+ * Input(2, 4, 3) Input(2, 4, 3)
+ * \ /
+ * \ /
+ * Pack
+ * |
+ * Output(2, 2, 4, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xf4, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
+ 0x78, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
+ 0x3c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x73, 0x74, 0x61, 0x63,
+ 0x6b, 0x5f, 0x34, 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x31, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data_1 = {
+ -0.17432976, -10.103649, 4.2064724, -7.185501, 7.6475716, -34.405083, 14.065273, -17.566177,
+ 16.921495, -8.886711, 16.913736, -8.991537, 18.480549, 17.71526, -3.8370514, 16.570705,
+ -14.831467, 17.709942, 0.026670456, -6.250948, 10.977406, 22.907639, -37.32604, -1.3433037};
+
+const std::vector<float> input_data_2 = {
+ -22.672482, 10.947399, -9.828194, -3.2829914, 14.490927, 24.998316, 33.86125, -17.046562,
+ 7.1629715, 21.064964, 5.813303, -16.67994, -22.828697, -7.9325237, -23.776447, -17.539246,
+ -3.8784523, 14.898129, 27.151598, -3.9495945, 21.426613, -8.786135, 0.22362137, -7.534506};
+
+const std::vector<float> reference_output_data = {
+ -1.7432976e-01, -1.0103649e+01, 4.2064724e+00, -7.1855011e+00, 7.6475716e+00, -3.4405083e+01,
+ 1.4065273e+01, -1.7566177e+01, 1.6921495e+01, -8.8867111e+00, 1.6913736e+01, -8.9915371e+00,
+ -2.2672482e+01, 1.0947399e+01, -9.8281937e+00, -3.2829914e+00, 1.4490927e+01, 2.4998316e+01,
+ 3.3861252e+01, -1.7046562e+01, 7.1629715e+00, 2.1064964e+01, 5.8133030e+00, -1.6679939e+01,
+ 1.8480549e+01, 1.7715260e+01, -3.8370514e+00, 1.6570705e+01, -1.4831467e+01, 1.7709942e+01,
+ 2.6670456e-02, -6.2509480e+00, 1.0977406e+01, 2.2907639e+01, -3.7326038e+01, -1.3433037e+00,
+ -2.2828697e+01, -7.9325237e+00, -2.3776447e+01, -1.7539246e+01, -3.8784523e+00, 1.4898129e+01,
+ 2.7151598e+01, -3.9495945e+00, 2.1426613e+01, -8.7861347e+00, 2.2362137e-01, -7.5345058e+00};
+} // namespace pack_float
+
+namespace pack_int
+{
+/*
+ * Pack Kernel:
+ *
+ * Input(2, 8) Input(2, 8)
+ * \ /
+ * \ /
+ * Pack
+ * |
+ * Output(2, 2, 8)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0xb8, 0x00, 0x00, 0x00, 0x24, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xa4, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00,
+ 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00, 0x6a, 0xff, 0xff, 0xff,
+ 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x31, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0xfe, 0xff, 0xff, 0xa8, 0xfe, 0xff, 0xff,
+ 0xac, 0xfe, 0xff, 0xff, 0xb0, 0xfe, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x6c, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3b, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x8a, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00,
+ 0x7c, 0xff, 0xff, 0xff, 0x05, 0x00, 0x00, 0x00, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0xc2, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0xb4, 0xff, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x00,
+ 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f, 0x31, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<int32_t> input_data_1 = {-5, 5, -5, -5, 15, 13, -4, 14,
+ 5, 5, 5, 5, 12, 21, -5, 6};
+const std::vector<int32_t> input_data_2 = {4, 5, 5, 5, 5, 5, 15, 4, -3, 11, 15, 32, -13, 13, -3, 5};
+
+const std::vector<int32_t> reference_output_data = {-5, 5, -5, -5, 15, 13, -4, 14, 5, 5, 5,
+ 5, 12, 21, -5, 6, 4, 5, 5, 5, 5, 5,
+ 15, 4, -3, 11, 15, 32, -13, 13, -3, 5};
+
+} // namespace pack_int
+
+namespace pack_quant_u8
+{
+/*
+ * Pack Kernel:
+ *
+ * Input(2, 4, 3) Input(2, 4, 3)
+ * \ /
+ * \ /
+ * Pack
+ * |
+ * Output(2, 2, 4, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x54, 0x02, 0x00, 0x00, 0x70, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xf4, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
+ 0x78, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1a, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+ 0x4c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x50, 0x00, 0x00, 0x00,
+ 0x0c, 0xff, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7f, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x73, 0x74, 0x61, 0x63, 0x6b, 0x5f, 0x34, 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x92, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x48, 0x00, 0x00, 0x00, 0x84, 0xff, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x31, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7f, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x69, 0x6e, 0x70, 0x75, 0x74, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<uint8_t> input_data_1 = {5, 243, 251, 5, 6, 7, 13, 23, 23, 5, 13, 5,
+ 7, 244, 13, 5, 5, 244, 252, 253, 5, 5, 5, 5};
+
+const std::vector<uint8_t> input_data_2 = {15, 30, 252, 7, 252, 40, 245, 13, 13, 14, 21, 5,
+ 5, 245, 251, 5, 251, 223, 5, 251, 22, 15, 15, 15};
+
+const std::vector<uint8_t> reference_output_data = {
+ 5, 243, 251, 5, 6, 7, 13, 23, 23, 5, 13, 5, 15, 30, 252, 7,
+ 252, 40, 245, 13, 13, 14, 21, 5, 7, 244, 13, 5, 5, 244, 252, 253,
+ 5, 5, 5, 5, 5, 245, 251, 5, 251, 223, 5, 251, 22, 15, 15, 15};
+
+} // namespace pack_quant_u8
+
+class TestDataFloatPack : public TestDataPackBase<float>
+{
+public:
+ TestDataFloatPack()
+ {
+ _input_data_1 = pack_float::input_data_1;
+ _input_data_2 = pack_float::input_data_2;
+ _reference_output_data = pack_float::reference_output_data;
+ _test_kernel_model_circle = pack_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatPack() override = default;
+};
+
+class TestDataIntPack : public TestDataPackBase<int32_t>
+{
+public:
+ TestDataIntPack()
+ {
+ _input_data_1 = pack_int::input_data_1;
+ _input_data_2 = pack_int::input_data_2;
+ _reference_output_data = pack_int::reference_output_data;
+ _test_kernel_model_circle = pack_int::test_kernel_model_circle;
+ }
+
+ ~TestDataIntPack() override = default;
+};
+
+class TestDataQuantU8Pack : public TestDataPackBase<uint8_t>
+{
+public:
+ TestDataQuantU8Pack()
+ {
+ _input_data_1 = pack_quant_u8::input_data_1;
+ _input_data_2 = pack_quant_u8::input_data_2;
+ _reference_output_data = pack_quant_u8::reference_output_data;
+ _test_kernel_model_circle = pack_quant_u8::test_kernel_model_circle;
+ }
+
+ ~TestDataQuantU8Pack() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_PACK_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/pack/TestDataPackBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/pack/TestDataPackBase.h
new file mode 100644
index 000000000..b587df311
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/pack/TestDataPackBase.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_PACK_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_PACK_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataPackBase : public TestDataBase<T>
+{
+public:
+ TestDataPackBase() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data_1;
+ case 1:
+ return _input_data_2;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data_1;
+ std::vector<T> _input_data_2;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_PACK_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/pad/FloatPadKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/pad/FloatPadKernel.h
new file mode 100644
index 000000000..ddfd3cf98
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/pad/FloatPadKernel.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_FLOAT_PAD_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_PAD_KERNEL_H
+
+#include "TestDataPadBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace pad_float
+{
+/*
+ * Pad Kernel:
+ *
+ * Input(1, 3, 3, 2)
+ * |
+ * Pad
+ * |
+ * Output(1, 3, 3, 2)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x4c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x9c, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {
+ -0.7942257, -1.3318212, -0.7918672, -1.0024637, -0.23364098, 0.49224994,
+ -0.23747201, -0.14768714, 1.4870708, -0.79761434, -0.27848604, 1.1856802,
+ 1.1039438, -0.34465268, -1.5857629, 3.0654314, 0.13304773, 0.067413524};
+
+const std::vector<float> reference_output_data = {
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0, -0.7942257, -1.3318212, -0.7918672,
+ -1.0024637, -0.23364098, 0.49224994, 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0, -0.23747201, -0.14768714, 1.4870708,
+ -0.79761434, -0.27848604, 1.1856802, 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0, 1.1039438, -0.34465268, -1.5857629,
+ 3.0654314, 0.13304773, 0.067413524, 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
+
+} // namespace pad_float
+
+class TestDataFloatPad : public TestDataPadBase<float>
+{
+public:
+ TestDataFloatPad()
+ {
+ _input_data = pad_float::input_data;
+ _reference_output_data = pad_float::reference_output_data;
+ _test_kernel_model_circle = pad_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatPad() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_PAD_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/pad/NegPadKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/pad/NegPadKernel.h
new file mode 100644
index 000000000..15936e449
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/pad/NegPadKernel.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_PAD_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_PAD_KERNEL_H
+
+#include "TestDataPadBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_pad_input_output_type_mismatch
+{
+/*
+ * Pad Kernel with input output type mismatch (should be equal):
+ *
+ * Input(1, 3, 3, 2) - Float
+ * |
+ * Pad
+ * |
+ * Output(1, 3, 3, 2) - Int
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0xa0, 0x01, 0x00, 0x00, 0xbc, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x4c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x22, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+} // namespace neg_pad_input_output_type_mismatch
+
+class NegTestDataInputOutputTypeMismatchPadKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInputOutputTypeMismatchPadKernel()
+ {
+ _test_kernel_model_circle = neg_pad_input_output_type_mismatch::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInputOutputTypeMismatchPadKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_PAD_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/pad/TestDataPadBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/pad/TestDataPadBase.h
new file mode 100644
index 000000000..e5c72def0
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/pad/TestDataPadBase.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_PAD_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_PAD_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataPadBase : public TestDataBase<T>
+{
+public:
+ TestDataPadBase() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_PAD_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/pad_v2/FloatPadV2Kernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/pad_v2/FloatPadV2Kernel.h
new file mode 100644
index 000000000..0aa00f884
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/pad_v2/FloatPadV2Kernel.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_FLOAT_PADV2_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_PADV2_KERNEL_H
+
+#include "TestDataPadV2Base.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace padV2_float
+{
+/*
+ * PadV2 Kernel:
+ *
+ * Input(1, 3, 3, 2)
+ * |
+ * PadV2
+ * |
+ * Output(1, 3, 3, 2)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xee, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff,
+ 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b,
+ 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xac, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x70, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x9c, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
+ 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64,
+ 0x69, 0x6e, 0x67, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {
+ -0.7942257, -1.3318212, -0.7918672, -1.0024637, -0.23364098, 0.49224994,
+ -0.23747201, -0.14768714, 1.4870708, -0.79761434, -0.27848604, 1.1856802,
+ 1.1039438, -0.34465268, -1.5857629, 3.0654314, 0.13304773, 0.067413524};
+
+const std::vector<float> reference_output_data = {
+ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0, -0.7942257, -1.3318212, -0.7918672,
+ -1.0024637, -0.23364098, 0.49224994, 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0, -0.23747201, -0.14768714, 1.4870708,
+ -0.79761434, -0.27848604, 1.1856802, 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0, 1.1039438, -0.34465268, -1.5857629,
+ 3.0654314, 0.13304773, 0.067413524, 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0};
+
+} // namespace padV2_float
+
+class TestDataFloatPadV2 : public TestDataPadV2Base<float>
+{
+public:
+ TestDataFloatPadV2()
+ {
+ _input_data = padV2_float::input_data;
+ _reference_output_data = padV2_float::reference_output_data;
+ _test_kernel_model_circle = padV2_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatPadV2() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_PADV2_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/pad_v2/NegPadV2Kernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/pad_v2/NegPadV2Kernel.h
new file mode 100644
index 000000000..2591a6016
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/pad_v2/NegPadV2Kernel.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_PADV2_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_PADV2_KERNEL_H
+
+#include "TestDataPadV2Base.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_padV2_input_output_type_mismatch
+{
+/*
+ * PadV2 Kernel with input output type mismatch (should be equal):
+ *
+ * Input(1, 3, 3, 2) - Float
+ * |
+ * PadV2
+ * |
+ * Output(1, 3, 3, 2) - Int
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0xe8, 0x01, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xee, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff,
+ 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b,
+ 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xb0, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xa4, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x9c, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x0f, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c,
+ 0x75, 0x65, 0x73, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+} // namespace neg_padV2_input_output_type_mismatch
+
+class NegTestDataInputOutputTypeMismatchPadV2Kernel : public NegTestDataBase
+{
+public:
+ NegTestDataInputOutputTypeMismatchPadV2Kernel()
+ {
+ _test_kernel_model_circle = neg_padV2_input_output_type_mismatch::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInputOutputTypeMismatchPadV2Kernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_PADV2_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/pad_v2/TestDataPadV2Base.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/pad_v2/TestDataPadV2Base.h
new file mode 100644
index 000000000..b94eb3cfa
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/pad_v2/TestDataPadV2Base.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_PADV2_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_PADV2_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataPadV2Base : public TestDataBase<T>
+{
+public:
+ TestDataPadV2Base() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_PADV2_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/reduce_common/NegReduceProdKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/reduce_common/NegReduceProdKernel.h
new file mode 100644
index 000000000..73d996b60
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/reduce_common/NegReduceProdKernel.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_REDUCE_PROD_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_REDUCE_PROD_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_wrong_type_mismatch_reduce_prod_kernel
+{
+/*
+ * ReduceProd Kernel with wrong input type:
+ *
+ * Input(5, 5) - Int16 Axis(1)
+ * \ /
+ * ReduceProd(keep_dims=false)
+ * |
+ * Output(5)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x4c, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
+ 0x72, 0x65, 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65,
+ 0x73, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x51, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_input_wrong_type_mismatch_reduce_prod_kernel
+
+namespace neg_axis_wrong_type_mismatch_reduce_prod_kernel
+{
+/*
+ * ReduceProd Kernel with wrong axis type:
+ *
+ * Input(5, 5) Axis(1) - Float32
+ * \ /
+ * ReduceProd(keep_dims=false)
+ * |
+ * Output(5)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x4c, 0x00, 0x00, 0x00, 0x6c, 0x01, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x40,
+ 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xb4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
+ 0x72, 0x65, 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65,
+ 0x73, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_axis_wrong_type_mismatch_reduce_prod_kernel
+
+class NegTestDataWrongInputTypeReduceProdKernel : public NegTestDataBase
+{
+public:
+ NegTestDataWrongInputTypeReduceProdKernel()
+ {
+ _test_kernel_model_circle =
+ neg_input_wrong_type_mismatch_reduce_prod_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataWrongInputTypeReduceProdKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataWrongAxisTypeReduceProdKernel : public NegTestDataBase
+{
+public:
+ NegTestDataWrongAxisTypeReduceProdKernel()
+ {
+ _test_kernel_model_circle =
+ neg_axis_wrong_type_mismatch_reduce_prod_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataWrongAxisTypeReduceProdKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_REDUCE_PROD_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/reduce_common/ReduceProdKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/reduce_common/ReduceProdKernel.h
new file mode 100644
index 000000000..be0a19ab5
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/reduce_common/ReduceProdKernel.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_REDUCE_PROD_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_REDUCE_PROD_KERNEL_H
+
+#include "TestDataReduceCommonBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace reduce_prod_float
+{
+/*
+ * ReduceProd Kernel:
+ *
+ * Input(5, 5) Axis(1)
+ * \ /
+ * ReduceProd(keep_dims=false)
+ * |
+ * Output(5)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0xd0, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x3c, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xbc, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00,
+ 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00, 0xda, 0xff, 0xff, 0xff,
+ 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x31, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xfe, 0xff, 0xff, 0xcc, 0xfe, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x38, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x92, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x84, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x50, 0x72, 0x6f, 0x64,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x14, 0x00, 0x00, 0x00, 0xc4, 0xff, 0xff, 0xff, 0x05, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x6e, 0x73,
+ 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63,
+ 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x51, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {11.411349, -16.127048, 2.1805973, 2.4134026, -24.384453,
+ 7.066084, -2.4375877, -6.3261166, 12.296496, -5.2269707,
+ -1.1958504, 39.85154, 11.011908, -15.1922455, -5.623905,
+ 12.9133, 17.127638, -5.8921337, 32.048306, -1.0499363,
+ 3.921646, -0.9553833, 0.16646576, -19.362396, 2.1621552};
+
+const std::vector<float> reference_output_data = {-4.8831299e+03, -2.5635121e+04, 1.4899535e+02,
+ 2.7976750e+05, 1.6272373e+03};
+} // namespace reduce_prod_float
+
+namespace reduce_prod_int
+{
+/*
+ * ReduceProd Kernel:
+ *
+ * Input(5, 5) Axis(1)
+ * \ /
+ * ReduceProd(keep_dims=false)
+ * |
+ * Output(5)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0xd0, 0x00, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00, 0x34, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xbc, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00,
+ 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00, 0xda, 0xff, 0xff, 0xff,
+ 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x31, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xfe, 0xff, 0xff, 0xd4, 0xfe, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x9e, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0x90, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x50, 0x72, 0x6f, 0x64, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0xce, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x05, 0x00, 0x00, 0x00,
+ 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<int32_t> input_data = {-2, -3, -5, 15, -11, 5, 5, 5, 7, 15, -12, 5, 5,
+ -3, 15, 22, -5, 24, 5, -13, -6, -4, -5, -3, 24};
+
+const std::vector<int32_t> reference_output_data = {-15840, -1500, 15000, 4725, 772200};
+} // namespace reduce_prod_int
+
+class TestDataFloatReduceProd : public TestDataReduceCommonBase<float>
+{
+public:
+ TestDataFloatReduceProd()
+ {
+ _input_data = reduce_prod_float::input_data;
+ _reference_output_data = reduce_prod_float::reference_output_data;
+ _test_kernel_model_circle = reduce_prod_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatReduceProd() override = default;
+};
+
+class TestDataIntReduceProd : public TestDataReduceCommonBase<int32_t>
+{
+public:
+ TestDataIntReduceProd()
+ {
+ _input_data = reduce_prod_int::input_data;
+ _reference_output_data = reduce_prod_int::reference_output_data;
+ _test_kernel_model_circle = reduce_prod_int::test_kernel_model_circle;
+ }
+
+ ~TestDataIntReduceProd() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_REDUCE_PROD_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/reduce_common/TestDataReduceCommonBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/reduce_common/TestDataReduceCommonBase.h
new file mode 100644
index 000000000..2cdddd735
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/reduce_common/TestDataReduceCommonBase.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_REDUCE_COMMON_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_REDUCE_COMMON_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataReduceCommonBase : public TestDataBase<T>
+{
+public:
+ TestDataReduceCommonBase() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_REDUCE_COMMON_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/relu/FloatReLUKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/relu/FloatReLUKernel.h
new file mode 100644
index 000000000..39cbdab74
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/relu/FloatReLUKernel.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_FLOAT_RELU_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_RELU_KERNEL_H
+
+#include "TestDataReLUBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace relu_float
+{
+/*
+ * ReLU Kernel:
+ *
+ * Input(1, 3, 3, 2)
+ * |
+ * ReLU
+ * |
+ * Output(1, 3, 3, 2)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff,
+ 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {4.5651245, -1.783557, 10.147356, 1.359064, 19.900585,
+ 31.432447, 3.4538271, -3.425167, 11.351466, -2.519806,
+ -2.702178, -15.201234, 15.547801, 10.433272, 4.301023,
+ 5.4106083, 0.14018308, -16.32785};
+const std::vector<float> reference_output_data = {
+ 4.5651245, 0.0, 10.147356, 1.359064, 19.900585, 31.432447, 3.4538271, 0.0, 11.351466,
+ 0.0, 0.0, 0.0, 15.547801, 10.433272, 4.301023, 5.4106083, 0.14018308, 0.0};
+
+} // namespace relu_float
+
+class TestDataFloatReLU : public TestDataReLUBase<float>
+{
+public:
+ TestDataFloatReLU()
+ {
+ _input_data = relu_float::input_data;
+ _reference_output_data = relu_float::reference_output_data;
+ _test_kernel_model_circle = relu_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatReLU() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_RELU_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/relu/NegReLUKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/relu/NegReLUKernel.h
new file mode 100644
index 000000000..54d1cb108
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/relu/NegReLUKernel.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_RELU_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_RELU_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_kernel
+{
+/*
+ * ReLU Kernel with input output type mismatch:
+ *
+ * Input(1, 3, 3, 2) - Float32
+ * |
+ * ReLU
+ * |
+ * Output(1, 3, 3, 2) - Int32
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff,
+ 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_input_output_type_mismatch_kernel
+
+class NegTestDataInputOutputTypeMismatchReLUKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInputOutputTypeMismatchReLUKernel()
+ {
+ _test_kernel_model_circle = neg_input_output_type_mismatch_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInputOutputTypeMismatchReLUKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_RELU_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/relu/TestDataReLUBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/relu/TestDataReLUBase.h
new file mode 100644
index 000000000..5e76fedf6
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/relu/TestDataReLUBase.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_RELU_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_RELU_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataReLUBase : public TestDataBase<T>
+{
+public:
+ TestDataReLUBase() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_RELU_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/relu6/FloatReLU6Kernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/relu6/FloatReLU6Kernel.h
new file mode 100644
index 000000000..7be41c12c
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/relu6/FloatReLU6Kernel.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_FLOAT_RELU6_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_RELU6_KERNEL_H
+
+#include "TestDataReLU6Base.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace relu6_float
+{
+/*
+ * ReLU6 Kernel:
+ *
+ * Input(1, 3, 3, 2)
+ * |
+ * ReLU6
+ * |
+ * Output(1, 3, 3, 2)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff,
+ 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {4.2436867, 11.136094, -10.418385, 9.319618, -4.471156,
+ -20.418179, 18.783192, 7.1997013, -9.659637, 6.2115526,
+ -4.2794833, 10.500693, 8.646875, 3.8725555, -21.104343,
+ -7.6522045, 1.0404004, 7.109288};
+const std::vector<float> reference_output_data = {4.2436867, 6.0, 0.0, 6.0, 0.0, 0.0,
+ 6.0, 6.0, 0.0, 6.0, 0.0, 6.0,
+ 6.0, 3.8725555, 0.0, 0.0, 1.0404004, 6.0};
+
+} // namespace relu6_float
+
+class TestDataFloatReLU6 : public TestDataReLU6Base<float>
+{
+public:
+ TestDataFloatReLU6()
+ {
+ _input_data = relu6_float::input_data;
+ _reference_output_data = relu6_float::reference_output_data;
+ _test_kernel_model_circle = relu6_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatReLU6() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_RELU6_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/relu6/NegReLU6Kernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/relu6/NegReLU6Kernel.h
new file mode 100644
index 000000000..e402d2759
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/relu6/NegReLU6Kernel.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_RELU6_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_RELU6_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_kernel
+{
+/*
+ * ReLU6 Kernel with input output type mismatch:
+ *
+ * Input(1, 3, 3, 2) - Float32
+ * |
+ * ReLU6
+ * |
+ * Output(1, 3, 3, 2) - Int32
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff,
+ 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_input_output_type_mismatch_kernel
+
+class NegTestDataInputOutputTypeMismatchReLU6Kernel : public NegTestDataBase
+{
+public:
+ NegTestDataInputOutputTypeMismatchReLU6Kernel()
+ {
+ _test_kernel_model_circle = neg_input_output_type_mismatch_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInputOutputTypeMismatchReLU6Kernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_LAEKY_RELU6_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/relu6/TestDataReLU6Base.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/relu6/TestDataReLU6Base.h
new file mode 100644
index 000000000..8e598328d
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/relu6/TestDataReLU6Base.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_RELU6_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_RELU6_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataReLU6Base : public TestDataBase<T>
+{
+public:
+ TestDataReLU6Base() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_RELU6_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/reshape/ReshapeKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/reshape/ReshapeKernel.h
new file mode 100644
index 000000000..60a42ff9f
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/reshape/ReshapeKernel.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_RESHAPE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_RESHAPE_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+namespace neg_reshape_kernel
+{
+/*
+ * Reshape Kernel with not const shape params
+ *
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xf4, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
+ 0x14, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xa8, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x73, 0x68, 0x61, 0x70, 0x65, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {-9.297554, 6.094736, 13.846724, -30.348026, 12.606297,
+ -25.089138, -18.258347, -8.119066, 0.24100876, 6.95887};
+
+const std::vector<float> reference_output_data = {-9.297554, 6.094736, 13.846724, -30.348026,
+ 12.606297, -25.089138, -18.258347, -8.119066,
+ 0.24100876, 6.95887};
+
+} // namespace neg_reshape_kernel
+
+namespace reshape_kernel
+{
+/*
+ * Reshape Kernel:
+ *
+ * Input(1, 1, 1, 10) Const([-1, 10])
+ * \ /
+ * Reshape
+ * |
+ * Output(1, 10)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x72, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0x0a, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
+ 0x7c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
+ 0x14, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa4, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x73, 0x68, 0x61, 0x70, 0x65, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {-9.297554, 6.094736, 13.846724, -30.348026, 12.606297,
+ -25.089138, -18.258347, -8.119066, 0.24100876, 6.95887};
+
+const std::vector<float> reference_output_data = {-9.297554, 6.094736, 13.846724, -30.348026,
+ 12.606297, -25.089138, -18.258347, -8.119066,
+ 0.24100876, 6.95887};
+
+} // namespace reshape_kernel
+
+template <typename T> class TestDataReshapeKernel : public TestDataBase<T>
+{
+public:
+ TestDataReshapeKernel(bool is_neg)
+ {
+ if (not is_neg)
+ {
+ _input_data = reshape_kernel::input_data;
+ _reference_output_data = reshape_kernel::reference_output_data;
+ _test_kernel_model_circle = reshape_kernel::test_kernel_model_circle;
+ }
+ else
+ {
+ _input_data = neg_reshape_kernel::input_data;
+ _reference_output_data = neg_reshape_kernel::reference_output_data;
+ _test_kernel_model_circle = neg_reshape_kernel::test_kernel_model_circle;
+ }
+ }
+
+ ~TestDataReshapeKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_RESHAPE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_bilinear/FloatResizeBilinearKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_bilinear/FloatResizeBilinearKernel.h
new file mode 100644
index 000000000..0ada18eae
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_bilinear/FloatResizeBilinearKernel.h
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_FLOAT_RESIZE_BILINEAR_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_RESIZE_BILINEAR_KERNEL_H
+
+#include "TestDataResizeBilinearBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace resize_bilinear_float
+{
+/*
+ * ResizeBilinear Kernel:
+ *
+ * align_corners = false; half_pixel_centers = false;
+ *
+ * Input(2, 2, 2, 1) FLOAT
+ * |
+ * | Constant Input(2) [3,3] INT32
+ * | /
+ * ResizeBilinear
+ * |
+ * Output(2, 3, 3, 1) FLOAT
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00,
+ 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0xa0, 0x01,
+ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00,
+ 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff,
+ 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00,
+ 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
+ 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0xa0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00,
+ 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x73, 0x69,
+ 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00,
+ 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00,
+ 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e,
+ 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00
+
+};
+
+const std::vector<float> input_data = {
+ 3, 6, //
+ 9, 12, //
+ 4, 10, //
+ 10, 16 //
+};
+
+const std::vector<float> reference_output_data = {
+ 3, 5, 6, //
+ 7, 9, 10, //
+ 9, 11, 12, //
+ 4, 8, 10, //
+ 8, 12, 14, //
+ 10, 14, 16, //
+};
+
+} // namespace resize_bilinear_float
+
+namespace resize_bilinear_float_half_pixel_centers
+{
+/*
+ * ResizeBilinear Kernel:
+ *
+ * align_corners = false; half_pixel_centers = true;
+ *
+ * Input(2, 2, 2, 1) FLOAT
+ * |
+ * | Constant Input(2) [3,3] INT32
+ * | /
+ * ResizeBilinear
+ * |
+ * Output(2, 3, 3, 1) FLOAT
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x4c, 0x00, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff,
+ 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x6c, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x78, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa0, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x73, 0x69, 0x7a, 0x65,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {
+ 1, 2, //
+ 3, 4, //
+ 1, 2, //
+ 3, 4 //
+};
+
+const std::vector<float> reference_output_data = {
+ 1, 1.5, 2, //
+ 2, 2.5, 3, //
+ 3, 3.5, 4, //
+ 1, 1.5, 2, //
+ 2, 2.5, 3, //
+ 3, 3.5, 4, //
+};
+
+} // namespace resize_bilinear_float_half_pixel_centers
+
+class TestDataFloatResizeBilinear : public TestDataResizeBilinearBase<float>
+{
+public:
+ TestDataFloatResizeBilinear(bool half_pixel_centers)
+ {
+ if (!half_pixel_centers)
+ {
+ _input_data = resize_bilinear_float::input_data;
+ _reference_output_data = resize_bilinear_float::reference_output_data;
+ _test_kernel_model_circle = resize_bilinear_float::test_kernel_model_circle;
+ }
+ else
+ {
+ _input_data = resize_bilinear_float_half_pixel_centers::input_data;
+ _reference_output_data = resize_bilinear_float_half_pixel_centers::reference_output_data;
+ _test_kernel_model_circle =
+ resize_bilinear_float_half_pixel_centers::test_kernel_model_circle;
+ }
+ }
+
+ ~TestDataFloatResizeBilinear() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_RESIZE_BILINEAR_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_bilinear/NegResizeBilinearKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_bilinear/NegResizeBilinearKernel.h
new file mode 100644
index 000000000..70133dcdb
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_bilinear/NegResizeBilinearKernel.h
@@ -0,0 +1,461 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_RESIZE_BILINEAR_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_RESIZE_BILINEAR_KERNEL_H
+
+#include "TestDataResizeBilinearBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_invalid_input_shape_float_resize_bilinear_kernel
+{
+/*
+ * ResizeBilinear Kernel (invalid_input_shape, dimensions should be 4):
+ *
+ * align_corners = false; half_pixel_centers = true;
+ *
+ * Input(2, 2, 2) FLOAT
+ * |
+ * | Constant Input(2) [3,3] INT32
+ * | /
+ * ResizeBilinear
+ * |
+ * Output(2, 3, 3, 1) FLOAT
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x4c, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0xac, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff,
+ 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x6c, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x78, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa0, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x73, 0x69, 0x7a, 0x65,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x17, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+} // namespace neg_invalid_input_shape_float_resize_bilinear_kernel
+
+namespace neg_invalid_param_float_resize_bilinear_kernel
+{
+/*
+ * ResizeBilinear Kernel (invalid params: should be only param true "align_corners" or
+ * "half_pixel_centers" ):
+ *
+ * align_corners = true; half_pixel_centers = true;
+ *
+ * Input(2, 2, 2, 1) FLOAT
+ * |
+ * | Constant Input(2) [3,3] INT32
+ * | /
+ * ResizeBilinear
+ * |
+ * Output(2, 3, 3, 1) FLOAT
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00,
+ 0x00, 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00,
+ 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00,
+ 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x70, 0x00,
+ 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0f, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x06, 0x00, 0x0c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
+ 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa0,
+ 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00,
+ 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10,
+ 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00,
+ 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10,
+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00,
+ 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x17,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00,
+ 0x00
+
+};
+
+} // namespace neg_invalid_param_float_resize_bilinear_kernel
+
+namespace neg_invalid_size_shape_dimensions_float_resize_bilinear_kernel
+{
+/*
+ * ResizeBilinear Kernel (invalid dimensions of the size shape ):
+ *
+ * align_corners = false; half_pixel_centers = false;
+ *
+ * Input(2, 2, 2, 1) FLOAT
+ * |
+ * | Constant Input(1) [3] INT32
+ * | /
+ * ResizeBilinear
+ * |
+ * Output(2, 3, 3, 1) FLOAT
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff,
+ 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
+ 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x17, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00
+
+};
+
+} // namespace neg_invalid_size_shape_dimensions_float_resize_bilinear_kernel
+
+namespace neg_invalid_input_shape_uint8_resize_bilinear_kernel
+{
+/*
+ * ResizeBilinear Kernel (invalid_input_shape, dimensions should be 4):
+ *
+ * align_corners = false; half_pixel_centers = true;
+ *
+ * Input(2, 2, 2) UINT8
+ * |
+ * | Constant Input(2) [3,3] INT32
+ * | /
+ * ResizeBilinear
+ * |
+ * Output(2, 3, 3, 1) UINT8
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x1c, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x3c, 0x02, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x5a, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x44, 0x00, 0x00, 0x00, 0x4c, 0xff, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x43, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_invalid_input_shape_uint8_resize_bilinear_kernel
+
+namespace neg_invalid_param_uint8_resize_bilinear_kernel
+{
+/*
+ * ResizeBilinear Kernel (invalid params: should be only param true "align_corners" or
+ * "half_pixel_centers" ):
+ *
+ * align_corners = true; half_pixel_centers = true;
+ *
+ * Input(2, 2, 2, 1) UINT8
+ * |
+ * | Constant Input(2) [3,3] INT32
+ * | /
+ * ResizeBilinear
+ * |
+ * Output(2, 3, 3, 1) UINT8
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x1c, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e,
+ 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00,
+ 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x3c,
+ 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04,
+ 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00,
+ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94,
+ 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00,
+ 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00,
+ 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0f, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x5a, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x44, 0x00, 0x00, 0x00, 0x4c, 0xff, 0xff, 0xff,
+ 0x2c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x43, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00,
+ 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x73, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00, 0x08, 0x00,
+ 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
+ 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x43,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d,
+ 0x31, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x17, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65,
+ 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00
+
+};
+} // namespace neg_invalid_param_uint8_resize_bilinear_kernel
+
+namespace neg_invalid_size_shape_dimensions_uint8_resize_bilinear_kernel
+{
+/*
+ * ResizeBilinear Kernel (invalid dimensions of the size shape ):
+ *
+ * align_corners = false; half_pixel_centers = false;
+ *
+ * Input(2, 2, 2, 1) UINT8
+ * |
+ * | Constant Input(1) [3] INT32
+ * | /
+ * ResizeBilinear
+ * |
+ * Output(2, 3, 3, 1) UINT8
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff,
+ 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
+ 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x17, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00
+
+};
+
+} // namespace neg_invalid_size_shape_dimensions_uint8_resize_bilinear_kernel
+
+class NegTestDataInvalidInputShapeFloatResizeBilinearKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInvalidInputShapeFloatResizeBilinearKernel()
+ {
+ _test_kernel_model_circle =
+ neg_invalid_input_shape_float_resize_bilinear_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInvalidInputShapeFloatResizeBilinearKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInvalidParamFloatResizeBilinearKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInvalidParamFloatResizeBilinearKernel()
+ {
+ _test_kernel_model_circle =
+ neg_invalid_param_float_resize_bilinear_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInvalidParamFloatResizeBilinearKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInvalidSizeShapeDimensionsFloatResizeBilinearKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInvalidSizeShapeDimensionsFloatResizeBilinearKernel()
+ {
+ _test_kernel_model_circle =
+ neg_invalid_size_shape_dimensions_float_resize_bilinear_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInvalidSizeShapeDimensionsFloatResizeBilinearKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInvalidInputShapeUint8ResizeBilinearKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInvalidInputShapeUint8ResizeBilinearKernel()
+ {
+ _test_kernel_model_circle =
+ neg_invalid_input_shape_uint8_resize_bilinear_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInvalidInputShapeUint8ResizeBilinearKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInvalidParamUint8ResizeBilinearKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInvalidParamUint8ResizeBilinearKernel()
+ {
+ _test_kernel_model_circle =
+ neg_invalid_param_uint8_resize_bilinear_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInvalidParamUint8ResizeBilinearKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInvalidSizeShapeDimensionsUint8ResizeBilinearKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInvalidSizeShapeDimensionsUint8ResizeBilinearKernel()
+ {
+ _test_kernel_model_circle =
+ neg_invalid_size_shape_dimensions_uint8_resize_bilinear_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInvalidSizeShapeDimensionsUint8ResizeBilinearKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_RESIZE_BILINEAR_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_bilinear/TestDataResizeBilinearBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_bilinear/TestDataResizeBilinearBase.h
new file mode 100644
index 000000000..218085111
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_bilinear/TestDataResizeBilinearBase.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_RESIZE_BILINEAR_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_RESIZE_BILINEAR_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataResizeBilinearBase : public TestDataBase<T>
+{
+public:
+ TestDataResizeBilinearBase() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_RESIZE_BILINEAR_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_bilinear/U8ResizeBilinearKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_bilinear/U8ResizeBilinearKernel.h
new file mode 100644
index 000000000..7c422b1e4
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_bilinear/U8ResizeBilinearKernel.h
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_UINT8_RESIZE_BILINEAR_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_UINT8_RESIZE_BILINEAR_KERNEL_H
+
+#include "TestDataResizeBilinearBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+namespace resize_bilinear_uint8
+{
+/*
+ * ResizeBilinear Kernel:
+ *
+ * align_corners = false; half_pixel_centers = false;
+ *
+ * Input(2, 2, 2, 1) UINT8
+ * |
+ * | Constant Input(2) [3,3] INT32
+ * | /
+ * ResizeBilinear
+ * |
+ * Output(2, 3, 3, 1) UINT8
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x1c, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00, 0x34, 0x02, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x5a, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x48, 0x00, 0x00, 0x00, 0x4c, 0xff, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x43, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x54, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00
+
+};
+
+const std::vector<uint8_t> input_data = {
+ 3, 6, //
+ 9, 12, //
+ 4, 10, //
+ 10, 16 //
+};
+
+const std::vector<uint8_t> reference_output_data = {
+ 3, 5, 6, //
+ 7, 9, 10, //
+ 9, 11, 12, //
+ 4, 8, 10, //
+ 8, 12, 14, //
+ 10, 14, 16, //
+};
+
+} // namespace resize_bilinear_uint8
+
+namespace resize_bilinear_uint8_half_pixel_centers
+{
+/*
+ * ResizeBilinear Kernel:
+ *
+ * align_corners = false; half_pixel_centers = true;
+ *
+ * Input(2, 2, 2, 1) UINT8
+ * |
+ * | Constant Input(2) [3,3] INT32
+ * | /
+ * ResizeBilinear
+ * |
+ * Output(2, 3, 3, 1) UINT8
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x1c, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x28, 0x02, 0x00, 0x00, 0x44, 0x02, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x18, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x07, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x5a, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x48, 0x00, 0x00, 0x00, 0x4c, 0xff, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x43, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x54, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00
+
+};
+
+const std::vector<uint8_t> input_data = {
+ 1, 2, //
+ 3, 4, //
+ 1, 2, //
+ 3, 4 //
+};
+
+const std::vector<uint8_t> reference_output_data = {
+ 1, 2, 2, //
+ 2, 3, 3, //
+ 3, 4, 4, //
+ 1, 2, 2, //
+ 2, 3, 3, //
+ 3, 4, 4, //
+};
+
+} // namespace resize_bilinear_uint8_half_pixel_centers
+
+class TestDataUint8ResizeBilinear : public TestDataResizeBilinearBase<uint8_t>
+{
+public:
+ TestDataUint8ResizeBilinear(bool half_pixel_centers)
+ {
+ if (!half_pixel_centers)
+ {
+ _input_data = resize_bilinear_uint8::input_data;
+ _reference_output_data = resize_bilinear_uint8::reference_output_data;
+ _test_kernel_model_circle = resize_bilinear_uint8::test_kernel_model_circle;
+ }
+ else
+ {
+ _input_data = resize_bilinear_uint8_half_pixel_centers::input_data;
+ _reference_output_data = resize_bilinear_uint8_half_pixel_centers::reference_output_data;
+ _test_kernel_model_circle =
+ resize_bilinear_uint8_half_pixel_centers::test_kernel_model_circle;
+ }
+ }
+
+ ~TestDataUint8ResizeBilinear() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_UINT8_RESIZE_BILINEAR_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/shape/NegShapeKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/shape/NegShapeKernel.h
new file mode 100644
index 000000000..5c7737a4a
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/shape/NegShapeKernel.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_SHAPE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_SHAPE_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_output_wrong_type_shape_kernel
+{
+/*
+ * Shape Kernel with wrong output type (should be INT32):
+ *
+ * Input(2, 3, 4)
+ * |
+ * Shape
+ * |
+ * Output(3) - FLOAT32
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x3c, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff,
+ 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x64, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xe0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4d, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_output_wrong_type_shape_kernel
+
+class NegTestDataWrongOutputTypeShapeKernel : public NegTestDataBase
+{
+public:
+ NegTestDataWrongOutputTypeShapeKernel()
+ {
+ _test_kernel_model_circle = neg_output_wrong_type_shape_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataWrongOutputTypeShapeKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_SHAPE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/shape/ShapeKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/shape/ShapeKernel.h
new file mode 100644
index 000000000..4be3f56f2
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/shape/ShapeKernel.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_SHAPE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_SHAPE_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+namespace shape_kernel
+{
+/*
+ * Shape Kernel:
+ *
+ * Input(2, 3, 4)
+ * |
+ * Shape
+ * |
+ * Output(3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff,
+ 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x64, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4d, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {
+ 9.817013, -10.169584, -11.175514, 6.3500366, -39.949837, 2.3447914, 14.254675, 20.6128,
+ 8.819141, -10.237312, -5.171467, 4.7246437, 11.657671, 20.094395, 11.213078, -13.8377495,
+ 10.846771, -15.841316, 7.4385757, -6.9196777, 12.076214, 18.011564, -14.684473, 2.7402115};
+
+const std::vector<int32_t> reference_output_data = {2, 3, 4};
+} // namespace shape_kernel
+
+template <typename T, typename U> class TestDataShapeKernel : public TestDataBase<T, U>
+{
+public:
+ TestDataShapeKernel()
+ {
+ _input_data = shape_kernel::input_data;
+ _reference_output_data = shape_kernel::reference_output_data;
+ _test_kernel_model_circle = shape_kernel::test_kernel_model_circle;
+ }
+
+ ~TestDataShapeKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<U> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<U> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_SHAPE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/slice/FloatSliceKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/slice/FloatSliceKernel.h
new file mode 100644
index 000000000..6586d37d0
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/slice/FloatSliceKernel.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_FLOAT_SLICE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_SLICE_KERNEL_H
+
+#include "TestDataSliceBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace slice_float
+{
+/*
+ * Slice Kernel:
+ *
+ * Input(3, 2, 3)
+ * |
+ * Slice
+ * |
+ * Output(1, 1, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00, 0x00, 0xe4, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x54, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff,
+ 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x30, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x7c, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xd8, 0xff, 0xff, 0xff,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {-6.0019245, -25.824707, -46.067307, -17.168013, -9.692509,
+ -42.846222, -18.903988, -26.145718, -10.458343, -27.042469,
+ -34.02651, -43.133247, 0.57390976, 9.837246, -22.825436,
+ 9.404066, -16.980595, -16.267637};
+
+const std::vector<float> reference_output_data = {-18.903988, -26.145718, -10.458343};
+
+} // namespace slice_float
+
+class TestDataFloatSlice : public TestDataSliceBase<float>
+{
+public:
+ TestDataFloatSlice()
+ {
+ _input_data = slice_float::input_data;
+ _reference_output_data = slice_float::reference_output_data;
+ _test_kernel_model_circle = slice_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatSlice() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_SLICE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/slice/NegSliceKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/slice/NegSliceKernel.h
new file mode 100644
index 000000000..2b59e8e5a
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/slice/NegSliceKernel.h
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_SLICE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_SLICE_KERNEL_H
+
+#include "TestDataSliceBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace slice_type_mismatch
+{
+/*
+ * Slice Kernel with input type != output_type:
+ *
+ * Input(3, 2, 3) - Float32
+ * |
+ * Slice
+ * |
+ * Output(1, 1, 3) - Int32
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0xcc, 0x01, 0x00, 0x00, 0xe8, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x54, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff,
+ 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x30, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xac, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0xd8, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x62, 0x65, 0x67, 0x69,
+ 0x6e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+} // namespace slice_type_mismatch
+
+namespace slice_wrong_begin_type
+{
+/*
+ * Slice Kernel with wrong begin type (should be int32 or int64):
+ *
+ * Input(3, 2, 3) Begin(3) - Float32
+ * | /
+ * Slice
+ * |
+ * Output(1, 1, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0xc4, 0x01, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x54, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff,
+ 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x30, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x73, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0xdc, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+} // namespace slice_wrong_begin_type
+
+namespace slice_wrong_size_type
+{
+/*
+ * Slice Kernel with wrong size type (should be int32 or int64):
+ *
+ * Input(3, 2, 3) Size(3) - Float32
+ * | /
+ * Slice
+ * |
+ * Output(1, 1, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0xc4, 0x01, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x54, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff,
+ 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x30, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xa8, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x73, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+} // namespace slice_wrong_size_type
+
+namespace slice_wrong_input_shape
+{
+/*
+ * Slice Kernel with wrong input shape (rank is 6 but should be <= 5):
+ *
+ * Input(3, 2, 3, 1, 1, 1)
+ * |
+ * Slice
+ * |
+ * Output(1, 1, 3, 1, 1, 1)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x54, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff,
+ 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x30, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x70, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd8, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x73, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+} // namespace slice_wrong_input_shape
+
+class TestDataTypeMismatchSlice : public NegTestDataBase
+{
+public:
+ TestDataTypeMismatchSlice()
+ {
+ _test_kernel_model_circle = slice_type_mismatch::test_kernel_model_circle;
+ }
+
+ ~TestDataTypeMismatchSlice() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class TestDataWrongBeginTypeSlice : public NegTestDataBase
+{
+public:
+ TestDataWrongBeginTypeSlice()
+ {
+ _test_kernel_model_circle = slice_wrong_begin_type::test_kernel_model_circle;
+ }
+
+ ~TestDataWrongBeginTypeSlice() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class TestDataWrongSizeTypeSlice : public NegTestDataBase
+{
+public:
+ TestDataWrongSizeTypeSlice()
+ {
+ _test_kernel_model_circle = slice_wrong_size_type::test_kernel_model_circle;
+ }
+
+ ~TestDataWrongSizeTypeSlice() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class TestDataWrongInputShapeSlice : public NegTestDataBase
+{
+public:
+ TestDataWrongInputShapeSlice()
+ {
+ _test_kernel_model_circle = slice_wrong_input_shape::test_kernel_model_circle;
+ }
+
+ ~TestDataWrongInputShapeSlice() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_SLICE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/slice/QuantS16SliceKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/slice/QuantS16SliceKernel.h
new file mode 100644
index 000000000..7d3d5a77f
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/slice/QuantS16SliceKernel.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_QUANT_S16_SLICE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_QUANT_S16_SLICE_KERNEL_H
+
+#include "TestDataSliceBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace slice_int16
+{
+/*
+ * Slice Kernel:
+ *
+ * Input(3, 2, 3)
+ * |
+ * Slice
+ * |
+ * Output(1, 1, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x1c, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x74, 0x02, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x64, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00,
+ 0x70, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3a, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x44, 0x00, 0x00, 0x00,
+ 0x2c, 0xff, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0xba, 0xc0, 0x40, 0x3d, 0x01, 0x00, 0x00, 0x00, 0x3e, 0x3f, 0xbf, 0x40,
+ 0x01, 0x00, 0x00, 0x00, 0xc2, 0xc0, 0xc0, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0xd8, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x62, 0x65, 0x67, 0x69,
+ 0x6e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+ 0x50, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0xba, 0xc0, 0x40, 0x3d, 0x01, 0x00, 0x00, 0x00, 0x3e, 0x3f, 0xbf, 0x40,
+ 0x01, 0x00, 0x00, 0x00, 0xc2, 0xc0, 0xc0, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<int16_t> input_data = {-24, -47, -23, -26, -23, -25, -24, -52, -14,
+ -23, -23, -23, -41, -24, -26, -22, -53, -23};
+
+const std::vector<int16_t> reference_output_data = {-24, -52, -14};
+
+} // namespace slice_int16
+
+class TestDataS16Slice : public TestDataSliceBase<int16_t>
+{
+public:
+ TestDataS16Slice()
+ {
+ _input_data = slice_int16::input_data;
+ _reference_output_data = slice_int16::reference_output_data;
+ _test_kernel_model_circle = slice_int16::test_kernel_model_circle;
+ }
+
+ ~TestDataS16Slice() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_QUANT_S16_SLICE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/slice/QuantU8SliceKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/slice/QuantU8SliceKernel.h
new file mode 100644
index 000000000..1f688d2d5
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/slice/QuantU8SliceKernel.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_QUANT_U8_SLICE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_QUANT_U8_SLICE_KERNEL_H
+
+#include "TestDataSliceBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace slice_uint8
+{
+/*
+ * Slice Kernel:
+ *
+ * Input(3, 2, 3)
+ * |
+ * Slice
+ * |
+ * Output(1, 1, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x1c, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x74, 0x02, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x64, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00,
+ 0x70, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3a, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x44, 0x00, 0x00, 0x00,
+ 0x2c, 0xff, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0xba, 0xc0, 0x40, 0x3d, 0x01, 0x00, 0x00, 0x00, 0x3e, 0x3f, 0xbf, 0x40,
+ 0x01, 0x00, 0x00, 0x00, 0xc2, 0xc0, 0xc0, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0xd8, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x62, 0x65, 0x67, 0x69,
+ 0x6e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x50, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0xba, 0xc0, 0x40, 0x3d, 0x01, 0x00, 0x00, 0x00, 0x3e, 0x3f, 0xbf, 0x40,
+ 0x01, 0x00, 0x00, 0x00, 0xc2, 0xc0, 0xc0, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<uint8_t> input_data = {3, 218, 233, 232, 234, 242, 238, 233, 218,
+ 240, 1, 233, 225, 242, 218, 249, 203, 225};
+
+const std::vector<uint8_t> reference_output_data = {238, 233, 218};
+
+} // namespace slice_uint8
+
+class TestDataU8Slice : public TestDataSliceBase<uint8_t>
+{
+public:
+ TestDataU8Slice()
+ {
+ _input_data = slice_uint8::input_data;
+ _reference_output_data = slice_uint8::reference_output_data;
+ _test_kernel_model_circle = slice_uint8::test_kernel_model_circle;
+ }
+
+ ~TestDataU8Slice() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_QUANT_U8_SLICE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/slice/TestDataSliceBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/slice/TestDataSliceBase.h
new file mode 100644
index 000000000..759a2488d
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/slice/TestDataSliceBase.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_SLICE_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_SLICE_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataSliceBase : public TestDataBase<T>
+{
+public:
+ TestDataSliceBase() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_SLICE_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/split/FloatSplitKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/split/FloatSplitKernel.h
new file mode 100644
index 000000000..7a9862780
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/split/FloatSplitKernel.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_SPLIT_KERNEL_FLOAT_H
+#define LUCI_INTERPRETER_TEST_MODELS_SPLIT_KERNEL_FLOAT_H
+
+#include "TestDataSplitBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace split_float
+{
+
+/*
+ * Split Kernel:
+ *
+ * Input(6, 1, 2) Split_dim(scalar=0)
+ * \ | /
+ * Split
+ * / \
+ * Output(3, 1, 2) Output(3, 1, 2)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0xbc, 0x01, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x72, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf4, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x23, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xa8, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x74, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xa0, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x73, 0x70, 0x6c, 0x69,
+ 0x74, 0x5f, 0x64, 0x69, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {20.07405, 30.467144, 34.943245, 38.18743,
+ 39.956573, 30.283304, 42.44296, 41.62288,
+ 16.24289, 38.450634, 27.079258, 47.636314};
+
+const std::vector<float> reference_output_data_1 = {20.07405, 30.467144, 34.943245,
+ 38.18743, 39.956573, 30.283304};
+const std::vector<float> reference_output_data_2 = {42.44296, 41.62288, 16.24289,
+ 38.450634, 27.079258, 47.636314};
+
+} // namespace split_float
+
+class TestDataFloatSplit : public TestDataSplitBase<float>
+{
+public:
+ TestDataFloatSplit()
+ {
+ _input_data = split_float::input_data;
+ _reference_output_data_1 = split_float::reference_output_data_1;
+ _reference_output_data_2 = split_float::reference_output_data_2;
+ _test_kernel_model_circle = split_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatSplit() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_SPLIT_KERNEL_FLOAT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/split/IntSplitKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/split/IntSplitKernel.h
new file mode 100644
index 000000000..87b898d58
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/split/IntSplitKernel.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_SPLIT_KERNEL_INT_H
+#define LUCI_INTERPRETER_TEST_MODELS_SPLIT_KERNEL_INT_H
+
+#include "TestDataSplitBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace split_int
+{
+
+/*
+ * Split Kernel:
+ *
+ * Input(6, 1, 2) Split_dim(scalar=0)
+ * \ | /
+ * Split
+ * / \
+ * Output(3, 1, 2) Output(3, 1, 2)
+ */
+
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0xbc, 0x01, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x72, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf4, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x23, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xa4, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x78, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0xa8, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0xd8, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x64, 0x69,
+ 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<int32_t> input_data = {40, 40, 30, 40, 35, 25, 35, 30, 35, 30, 40, 35};
+
+const std::vector<int32_t> reference_output_data_1 = {40, 40, 30, 40, 35, 25};
+const std::vector<int32_t> reference_output_data_2 = {35, 30, 35, 30, 40, 35};
+
+} // namespace split_int
+
+class TestDataIntSplit : public TestDataSplitBase<int32_t>
+{
+public:
+ TestDataIntSplit()
+ {
+ _input_data = split_int::input_data;
+ _reference_output_data_1 = split_int::reference_output_data_1;
+ _reference_output_data_2 = split_int::reference_output_data_2;
+ _test_kernel_model_circle = split_int::test_kernel_model_circle;
+ }
+
+ ~TestDataIntSplit() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_SPLIT_KERNEL_INT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/split/TestDataSplitBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/split/TestDataSplitBase.h
new file mode 100644
index 000000000..7ddcd75d5
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/split/TestDataSplitBase.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_SPLIT_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_SPLIT_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataSplitBase : public TestDataBase<T>
+{
+public:
+ TestDataSplitBase() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _reference_output_data_1;
+ case 1:
+ return _reference_output_data_2;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data_1;
+ std::vector<T> _reference_output_data_2;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_SPLIT_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/split_v/SplitVKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/split_v/SplitVKernel.h
new file mode 100644
index 000000000..bb87c4068
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/split_v/SplitVKernel.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_SPLIT_V_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_SPLIT_V_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+namespace split_v_kernel
+{
+/*
+ * SplitV Kernel:
+ *
+ * Input(6, 1, 2) Size_splits([1, 2, 3]) Split_dim(scalar=0)
+ * \ | /
+ * SplitV
+ * / | \
+ * Output(1, 1, 2) Output(2, 1, 2) Output(3, 1, 2)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x6c, 0x00, 0x00, 0x00, 0x4c, 0x02, 0x00, 0x00, 0x68, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x56, 0xff, 0xff, 0xff,
+ 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0xff, 0xff, 0xff,
+ 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xf4, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff,
+ 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x08, 0x01, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1c, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x33,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x48, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x74, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xd8, 0xff, 0xff, 0xff,
+ 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00,
+ 0x09, 0x00, 0x00, 0x00, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x64, 0x69, 0x6d, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x14, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x73, 0x70, 0x6c,
+ 0x69, 0x74, 0x73, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {-3.9030151, -4.558613, -12.806297, -2.64188,
+ 17.035677, 26.150639, -12.618465, 0.8286438,
+ -4.850197, -0.20810127, 3.8918018, 4.1862106};
+
+const std::vector<float> reference_output_data_1 = {-3.9030151, -4.558613};
+const std::vector<float> reference_output_data_2 = {-12.806297, -2.64188, 17.035677, 26.150639};
+const std::vector<float> reference_output_data_3 = {-12.618465, 0.8286438, -4.850197,
+ -0.20810127, 3.8918018, 4.1862106};
+
+} // namespace split_v_kernel
+
+template <typename T> class TestDataSplitVKernel : public TestDataBase<T>
+{
+public:
+ TestDataSplitVKernel()
+ {
+ _input_data = split_v_kernel::input_data;
+ _reference_output_data_1 = split_v_kernel::reference_output_data_1;
+ _reference_output_data_2 = split_v_kernel::reference_output_data_2;
+ _reference_output_data_3 = split_v_kernel::reference_output_data_3;
+ _test_kernel_model_circle = split_v_kernel::test_kernel_model_circle;
+ }
+
+ ~TestDataSplitVKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _reference_output_data_1;
+ case 1:
+ return _reference_output_data_2;
+ case 2:
+ return _reference_output_data_3;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data_1;
+ std::vector<T> _reference_output_data_2;
+ std::vector<T> _reference_output_data_3;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_SPLIT_V_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/strided_slice/StridedSliceKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/strided_slice/StridedSliceKernel.h
new file mode 100644
index 000000000..4d69013ff
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/strided_slice/StridedSliceKernel.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_STRIDED_SLICE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_STRIDED_SLICE_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+namespace strided_slice_kernel
+{
+/*
+ * StridedSlice Kernel:
+ *
+ * Input(3, 2, 3) Begin([1, 0, 0]) End([2, 1, 3]) Strides([1, 1, 1])
+ * | | | |
+ * ------------------- | | ------------------
+ * \ | | /
+ * StridedSlice
+ * |
+ * Output(1, 1, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x84, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x2c, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x70, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xce, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0xe6, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff,
+ 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x70, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x58, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0xb4, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x73, 0x74, 0x72, 0x69, 0x64, 0x65, 0x73, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xdc, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x65, 0x6e, 0x64, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x62, 0x65, 0x67, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x2d, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {15.78072, -20.820415, 17.688091, 12.961567, -5.469105,
+ -7.867565, -6.989258, -9.068207, 4.974188, 6.2882156,
+ 7.269455, 6.161186, 15.821367, -17.094833, 24.529251,
+ 1.1271019, -8.563269, -7.494442};
+
+const std::vector<float> reference_output_data = {-6.989258, -9.068207, 4.974188};
+
+} // namespace strided_slice_kernel
+
+template <typename T> class TestDataStridedSliceKernel : public TestDataBase<T>
+{
+public:
+ TestDataStridedSliceKernel()
+ {
+ _input_data = strided_slice_kernel::input_data;
+ _reference_output_data = strided_slice_kernel::reference_output_data;
+ _test_kernel_model_circle = strided_slice_kernel::test_kernel_model_circle;
+ }
+
+ ~TestDataStridedSliceKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_STRIDED_SLICE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sub/FloatSubKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sub/FloatSubKernel.h
new file mode 100644
index 000000000..25f83865b
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sub/FloatSubKernel.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_SUB_KERNEL_FLOAT_H
+#define LUCI_INTERPRETER_TEST_MODELS_SUB_KERNEL_FLOAT_H
+
+#include "TestDataSubBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace sub_float_with_broadcasting
+{
+
+/*
+ * Sub Kernel:
+ *
+ * Input_1(2, 5) Input_2(2, 1)
+ * \ /
+ * Sub(with broadcast)
+ * |
+ * Output(2, 5)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0xc0, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x28, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xac, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x31, 0x2e, 0x36, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc4, 0xfe, 0xff, 0xff, 0xc8, 0xfe, 0xff, 0xff, 0xcc, 0xfe, 0xff, 0xff, 0xd0, 0xfe, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3c, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00,
+ 0x53, 0x75, 0x62, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0xc6, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63,
+ 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f, 0x31, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x10, 0x00,
+ 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x65, 0x72, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input1_data = {-8.326889, -1.022953, 0.1884613, 22.581654, 40.9168,
+ 36.762, -9.715984, 4.0496464, 31.648043, 11.501019};
+const std::vector<float> input2_data = {15.127094, 3.3150635};
+const std::vector<float> reference_output_data = {-23.453983, -16.150047, -14.938633, 7.4545593,
+ 25.789707, 33.446938, -13.031048, 0.7345829,
+ 28.33298, 8.185955};
+
+} // namespace sub_float_with_broadcasting
+
+namespace sub_float_no_broadcasting
+{
+/*
+ * Sub Kernel:
+ *
+ * Input_1(2, 5) Input_2(2, 5)
+ * \ /
+ * Sub(no broadcast)
+ * |
+ * Output(2, 5)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0xc0, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x28, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xac, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x31, 0x2e, 0x36, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc4, 0xfe, 0xff, 0xff, 0xc8, 0xfe, 0xff, 0xff, 0xcc, 0xfe, 0xff, 0xff, 0xd0, 0xfe, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3c, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00,
+ 0x53, 0x75, 0x62, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0xc6, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63,
+ 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f, 0x31, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x10, 0x00,
+ 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x65, 0x72, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+std::vector<float> input1_data = {-12.091457, 7.402893, 5.7398167, 1.6491795, 12.5600815,
+ 13.821102, 8.744585, 11.44549, -0.7579155, 4.1162605};
+std::vector<float> input2_data = {13.1849, 12.109516, -0.026350021, -5.5562515, -3.3528423,
+ 10.397262, 25.990755, 19.270943, -26.921743, 3.6311188};
+std::vector<float> reference_output_data = {-25.276358, -4.706623, 5.7661667, 7.205431,
+ 15.912924, 3.4238405, -17.24617, -7.825453,
+ 26.163828, 0.48514175};
+
+} // namespace sub_float_no_broadcasting
+
+class TestDataFloatSub : public TestDataSubBase<float>
+{
+public:
+ explicit TestDataFloatSub(bool is_with_broadcast) : TestDataSubBase<float>(is_with_broadcast)
+ {
+ if (is_with_broadcast)
+ {
+ _input1_data = sub_float_with_broadcasting::input1_data;
+ _input2_data = sub_float_with_broadcasting::input2_data;
+ _reference_output_data = sub_float_with_broadcasting::reference_output_data;
+ _test_kernel_model_circle = sub_float_with_broadcasting::test_kernel_model_circle;
+ }
+ else
+ {
+ _input1_data = sub_float_no_broadcasting::input1_data;
+ _input2_data = sub_float_no_broadcasting::input2_data;
+ _reference_output_data = sub_float_no_broadcasting::reference_output_data;
+ _test_kernel_model_circle = sub_float_no_broadcasting::test_kernel_model_circle;
+ }
+ }
+
+ ~TestDataFloatSub() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_SUB_KERNEL_FLOAT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sub/IntSubKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sub/IntSubKernel.h
new file mode 100644
index 000000000..81d0edc87
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sub/IntSubKernel.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_SUB_KERNEL_INT_H
+#define LUCI_INTERPRETER_TEST_MODELS_SUB_KERNEL_INT_H
+
+#include "TestDataSubBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace sub_int_with_broadcasting
+{
+
+/*
+ * Sub Kernel:
+ *
+ * Input_1(2, 5) Input_2(2, 1)
+ * \ /
+ * Sub(with broadcast)
+ * |
+ * Output(2, 5)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0xc0, 0x00, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00, 0x34, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xac, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x31, 0x2e, 0x36, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xb8, 0xfe, 0xff, 0xff, 0xbc, 0xfe, 0xff, 0xff, 0xc0, 0xfe, 0xff, 0xff, 0xc4, 0xfe, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x84, 0xff, 0xff, 0xff,
+ 0x03, 0x00, 0x00, 0x00, 0x53, 0x75, 0x62, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0xc2, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0xb4, 0xff, 0xff, 0xff,
+ 0x0d, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f,
+ 0x31, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<int32_t> input1_data = {13, 23, 5, -3, 15, 5, 5, 5, 13, 12};
+const std::vector<int32_t> input2_data = {5, 13};
+const std::vector<int32_t> reference_output_data = {8, 18, 0, -8, 10, -8, -8, -8, 0, -1};
+
+} // namespace sub_int_with_broadcasting
+
+namespace sub_int_no_broadcasting
+{
+/*
+ * Sub Kernel:
+ *
+ * Input_1(2, 5) Input_2(2, 5)
+ * \ /
+ * Sub(no broadcast)
+ * |
+ * Output(2, 5)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0xc0, 0x00, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00, 0x34, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0xac, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x31, 0x2e, 0x36, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xb8, 0xfe, 0xff, 0xff, 0xbc, 0xfe, 0xff, 0xff, 0xc0, 0xfe, 0xff, 0xff, 0xc4, 0xfe, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x84, 0xff, 0xff, 0xff,
+ 0x03, 0x00, 0x00, 0x00, 0x53, 0x75, 0x62, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0xc2, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0xb4, 0xff, 0xff, 0xff,
+ 0x0d, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f,
+ 0x31, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+
+std::vector<int32_t> input1_data = {5, 7, 13, -3, 13, 7, -5, 5, 13, 5};
+std::vector<int32_t> input2_data = {-5, -11, 5, 5, 14, 5, 42, 6, 5, 15};
+std::vector<int32_t> reference_output_data = {10, 18, 8, -8, -1, 2, -47, -1, 8, -10};
+
+} // namespace sub_int_no_broadcasting
+
+class TestDataIntSub : public TestDataSubBase<int32_t>
+{
+public:
+ explicit TestDataIntSub(bool is_with_broadcast) : TestDataSubBase<int32_t>(is_with_broadcast)
+ {
+ if (is_with_broadcast)
+ {
+ _input1_data = sub_int_with_broadcasting::input1_data;
+ _input2_data = sub_int_with_broadcasting::input2_data;
+ _reference_output_data = sub_int_with_broadcasting::reference_output_data;
+ _test_kernel_model_circle = sub_int_with_broadcasting::test_kernel_model_circle;
+ }
+ else
+ {
+ _input1_data = sub_int_no_broadcasting::input1_data;
+ _input2_data = sub_int_no_broadcasting::input2_data;
+ _reference_output_data = sub_int_no_broadcasting::reference_output_data;
+ _test_kernel_model_circle = sub_int_no_broadcasting::test_kernel_model_circle;
+ }
+ }
+
+ ~TestDataIntSub() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_SUB_KERNEL_INT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sub/NegSubKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sub/NegSubKernel.h
new file mode 100644
index 000000000..d5ea240d4
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sub/NegSubKernel.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_SUB_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_SUB_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_inputs_type_mismatch_sub_kernel
+{
+/*
+ * Sub Kernel with inputs type mismatch:
+ *
+ * Input_1(1, 5, 2, 3)-Int Input_2(1, 5, 2, 3)-Float
+ * \ /
+ * Sub(no broadcast)
+ * |
+ * Output(1, 5, 2, 3)-Float
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x94, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_inputs_type_mismatch_sub_kernel
+
+namespace neg_input_output_type_mismatch_sub_kernel
+{
+/*
+ * Sub Kernel with input output types mismatch:
+ *
+ * Input_1(1, 5, 2, 3)-Float Input_2(1, 5, 2, 3)-Float
+ * \ /
+ * Sub(no broadcast)
+ * |
+ * Output(1, 5, 2, 3)-Int
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_input_output_type_mismatch_sub_kernel
+
+namespace neg_no_quant_params_sub_kernel
+{
+/*
+ * Sub S16 Kernel without quant params:
+ *
+ * Input_1(1, 5, 2, 3)-Int16 Input_2(1, 5, 2, 3)-Int16
+ * \ /
+ * Sub(no broadcast, no quant params)
+ * |
+ * Output(1, 5, 2, 3)-Int16
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x88, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9c, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xcc, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x11, 0x00, 0x00, 0x00,
+ 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_no_quant_params_sub_kernel
+
+class NegTestDataInputsTypeMismatchSubKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInputsTypeMismatchSubKernel()
+ {
+ _test_kernel_model_circle = neg_inputs_type_mismatch_sub_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInputsTypeMismatchSubKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInputOutputTypeMismatchSubKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInputOutputTypeMismatchSubKernel()
+ {
+ _test_kernel_model_circle = neg_input_output_type_mismatch_sub_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInputOutputTypeMismatchSubKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataNoQuantParamsSubKernel : public NegTestDataBase
+{
+public:
+ NegTestDataNoQuantParamsSubKernel()
+ {
+ _test_kernel_model_circle = neg_no_quant_params_sub_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataNoQuantParamsSubKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_SUB_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sub/TestDataSubBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sub/TestDataSubBase.h
new file mode 100644
index 000000000..8c0775e7b
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sub/TestDataSubBase.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_SUB_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_SUB_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataSubBase : public TestDataBase<T>
+{
+public:
+ explicit TestDataSubBase(bool)
+ {
+ // Do nothing
+ }
+
+ TestDataSubBase() = delete;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input1_data;
+ case 1:
+ return _input2_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input1_data;
+ std::vector<T> _input2_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_SUB_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/tanh/FloatTanhKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/tanh/FloatTanhKernel.h
new file mode 100644
index 000000000..82ce797cc
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/tanh/FloatTanhKernel.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_FLOAT_TANH_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_TANH_KERNEL_H
+
+#include "TestDataTanhBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace tanh_float
+{
+/*
+ * Tanh Kernel:
+ *
+ * Input(1, 3, 3, 2)
+ * |
+ * Tanh
+ * |
+ * Output(1, 3, 3, 2)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff,
+ 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {-18.051472, -25.18281, -1.566864, 10.271992, 9.358999,
+ 30.315918, 22.305614, 4.2511578, 5.960436, -8.210682,
+ 21.21092, -18.009472, -13.981232, -3.081173, 7.770035,
+ 7.670355, 21.851545, 17.201824};
+
+const std::vector<float> reference_output_data = {
+ -1.0, -1.0, -0.9165255, 1.0, 1.0, 1.0, 1.0, 0.99959403, 0.99998677,
+ -1.0, 1.0, -1.0, -1.0, -0.9957943, 0.9999997, 0.99999964, 1.0, 1.0};
+
+} // namespace tanh_float
+
+class TestDataFloatTanh : public TestDataTanhBase<float>
+{
+public:
+ TestDataFloatTanh()
+ {
+ _input_data = tanh_float::input_data;
+ _reference_output_data = tanh_float::reference_output_data;
+ _test_kernel_model_circle = tanh_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatTanh() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_TANH_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/tanh/NegTanhKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/tanh/NegTanhKernel.h
new file mode 100644
index 000000000..3ff0b6832
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/tanh/NegTanhKernel.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_TANH_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_TANH_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_kernel
+{
+/*
+ * Tanh Kernel with input output type mismatch:
+ *
+ * Input(1, 3, 3, 2) - Float32
+ * |
+ * Tanh
+ * |
+ * Output(1, 3, 3, 2) - Int32
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff,
+ 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_input_output_type_mismatch_kernel
+
+class NegTestDataInputOutputTypeMismatchTanhKernel : public NegTestDataBase
+{
+public:
+ NegTestDataInputOutputTypeMismatchTanhKernel()
+ {
+ _test_kernel_model_circle = neg_input_output_type_mismatch_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataInputOutputTypeMismatchTanhKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_TANH_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/tanh/TestDataTanhBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/tanh/TestDataTanhBase.h
new file mode 100644
index 000000000..2e12dfec1
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/tanh/TestDataTanhBase.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_TANH_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_TANH_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataTanhBase : public TestDataBase<T>
+{
+public:
+ TestDataTanhBase() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_TANH_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/transpose/TransposeKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/transpose/TransposeKernel.h
new file mode 100644
index 000000000..ebeda65c0
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/transpose/TransposeKernel.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_TRANSPOSE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_TRANSPOSE_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+namespace transpose_kernel
+{
+/*
+ * Transpose Kernel:
+ *
+ * Input(3, 8, 1) Perm([1, 2, 0])
+ * \ /
+ * Transpose
+ * |
+ * Output(8, 1, 3)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x4c, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xa4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x70, 0x65, 0x72, 0x6d,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {
+ 20.761623, 13.150787, 7.0800495, -5.8079357, -4.265215, -2.801073, 14.42078, 8.526264,
+ 27.862984, 1.067873, 19.894545, 0.25564194, 10.414932, 3.317482, -0.727417, -5.702162,
+ -2.8192825, 19.296608, 23.116634, 6.5216866, -7.0733185, -3.3730087, -34.845665, 28.050354};
+
+const std::vector<float> reference_output_data = {
+ 20.761623, 27.862984, -2.8192825, 13.150787, 1.067873, 19.296608, 7.0800495, 19.894545,
+ 23.116634, -5.8079357, 0.25564194, 6.5216866, -4.265215, 10.414932, -7.0733185, -2.801073,
+ 3.317482, -3.3730087, 14.42078, -0.727417, -34.845665, 8.526264, -5.702162, 28.050354};
+} // namespace transpose_kernel
+
+template <typename T> class TestDataTransposeKernel : public TestDataBase<T>
+{
+public:
+ TestDataTransposeKernel()
+ {
+ _input_data = transpose_kernel::input_data;
+ _reference_output_data = transpose_kernel::reference_output_data;
+ _test_kernel_model_circle = transpose_kernel::test_kernel_model_circle;
+ }
+
+ ~TestDataTransposeKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_TRANSPOSE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/unidirectional_lstm/FloatUnidirectionalLSTMKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/unidirectional_lstm/FloatUnidirectionalLSTMKernel.h
new file mode 100644
index 000000000..ea9674875
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/unidirectional_lstm/FloatUnidirectionalLSTMKernel.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_FLOAT_UNIDIRECTIONAL_LSTM_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_UNIDIRECTIONAL_LSTM_KERNEL_H
+
+#include "TestDataUnidirectionalLSTMBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace unidir_lstm_float
+{
+/*
+ * UnidirectionalLSTM Kernel:
+ *
+ * Input(1, 4, 4)
+ * |
+ * UnidirectionalLSTM
+ * |
+ * Output(1, 4, 2)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0xb4, 0x01, 0x00, 0x00, 0xd0, 0x05, 0x00, 0x00, 0xec, 0x05, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
+ 0xa0, 0x01, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00,
+ 0x64, 0x01, 0x00, 0x00, 0x3c, 0x01, 0x00, 0x00, 0x1c, 0x01, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00,
+ 0xe4, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x3c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa0, 0xfe, 0xff, 0xff,
+ 0xd2, 0xfe, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x84, 0x9b, 0x3c, 0xbe,
+ 0x48, 0xfc, 0x22, 0xbf, 0x35, 0x43, 0xba, 0x3e, 0x18, 0x5c, 0xdb, 0x3e, 0x4b, 0x05, 0xdd, 0xbe,
+ 0xf5, 0x0f, 0x1e, 0xbf, 0x1f, 0x2e, 0x09, 0x3f, 0x9e, 0xb5, 0x2f, 0x3f, 0xfe, 0xfe, 0xff, 0xff,
+ 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xca, 0xfe, 0x05, 0x3f, 0xea, 0x91, 0x06, 0xbe,
+ 0x77, 0xf4, 0xa7, 0xbe, 0x3f, 0x02, 0x23, 0xbf, 0xd1, 0xdc, 0x94, 0xbd, 0xc2, 0xdd, 0xb1, 0xbe,
+ 0x45, 0x13, 0xc8, 0x3e, 0x7f, 0x6b, 0xef, 0x3e, 0x2a, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0xec, 0xde, 0xe2, 0xbe, 0xf6, 0x46, 0x01, 0xbf, 0xed, 0x4d, 0x97, 0xbd,
+ 0xf2, 0xed, 0x09, 0xbf, 0x88, 0x4c, 0xe1, 0x3e, 0x60, 0x74, 0x89, 0x3e, 0x29, 0x79, 0x75, 0x3c,
+ 0x9b, 0x8f, 0xdb, 0xbe, 0x56, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0xe7, 0xc8, 0x6a, 0x3e, 0x16, 0x06, 0x8b, 0xbd, 0x49, 0xf5, 0xe5, 0x3e, 0x01, 0xfb, 0xf0, 0x3e,
+ 0x7c, 0x48, 0x10, 0xbf, 0x12, 0xd8, 0x94, 0xbe, 0x9a, 0xec, 0xaf, 0x3e, 0x4c, 0x1a, 0xdb, 0xbe,
+ 0x82, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
+ 0x00, 0x00, 0x80, 0x3f, 0x96, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x8d, 0xd4, 0xdb, 0xbd, 0xfe, 0x63, 0xd1, 0x3e, 0x9f, 0x60, 0x1a, 0x3d,
+ 0xa1, 0x48, 0x0b, 0xbf, 0xc6, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x3a, 0xb2, 0xca, 0x3e, 0x58, 0x1a, 0x04, 0xbf, 0xe6, 0x76, 0x9f, 0x3e, 0x61, 0xa7, 0xd8, 0x3e,
+ 0xe2, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xf1, 0x48, 0x5c, 0xbe,
+ 0xcd, 0x54, 0xad, 0x3c, 0x9f, 0x8e, 0xbf, 0x3e, 0x69, 0xac, 0xfd, 0x3d, 0x00, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x93, 0x70, 0x21, 0xbf, 0x76, 0x27, 0x8e, 0x3c, 0x97, 0xe3, 0xc5, 0x3e, 0xe5, 0x7d, 0x8c, 0x3e,
+ 0xf4, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
+ 0xcc, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x00, 0x04,
+ 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x06, 0x00, 0x00, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x0d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0xe4, 0x02, 0x00, 0x00, 0x98, 0x02, 0x00, 0x00, 0x54, 0x02, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00,
+ 0xec, 0x01, 0x00, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00, 0x58, 0x01, 0x00, 0x00,
+ 0x24, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x60, 0xfd, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x66, 0x75, 0x6c, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x43,
+ 0x61, 0x6c, 0x6c, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xec, 0xfd, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
+ 0x0c, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
+ 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f, 0x6c, 0x73, 0x74, 0x6d, 0x2f,
+ 0x7a, 0x65, 0x72, 0x6f, 0x73, 0x31, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0xdc, 0xfd, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x61, 0x72, 0x69, 0x74, 0x68, 0x2e, 0x63, 0x6f,
+ 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x39, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x0c, 0xfe, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x61, 0x72, 0x69, 0x74, 0x68, 0x2e, 0x63, 0x6f,
+ 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x38, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x3c, 0xfe, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x61, 0x72, 0x69, 0x74, 0x68, 0x2e, 0x63, 0x6f,
+ 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x37, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x61, 0x72, 0x69, 0x74, 0x68, 0x2e, 0x63, 0x6f,
+ 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x36, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x9c, 0xfe, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x61, 0x72, 0x69, 0x74, 0x68, 0x2e, 0x63, 0x6f,
+ 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x35, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0xc8, 0xfe, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x0f, 0x00, 0x00, 0x00, 0x61, 0x72, 0x69, 0x74, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61,
+ 0x6e, 0x74, 0x34, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xf4, 0xfe, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
+ 0x61, 0x72, 0x69, 0x74, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x33, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x24, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
+ 0x61, 0x72, 0x69, 0x74, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x32, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
+ 0x61, 0x72, 0x69, 0x74, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x31, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x84, 0xff, 0xff, 0xff,
+ 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x61, 0x72, 0x69, 0x74, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x14, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x15, 0x00, 0x00, 0x00, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f, 0x6c,
+ 0x73, 0x74, 0x6d, 0x2f, 0x7a, 0x65, 0x72, 0x6f, 0x73, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x5f,
+ 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x31, 0x3a,
+ 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x2c, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69,
+ 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {
+ -3.509163, -18.256927, 6.4799614, 10.296598, 30.371328, 18.692572, 10.12867, -26.44944,
+ 25.324795, 3.8303719, 20.93112, 22.603086, -4.308655, 2.3276749, -5.9565907, 25.611776};
+
+const std::vector<float> reference_output_data = {0.7613201, -0.7570043, 0.0480366,
+ -4.3364323e-11, -0.7613433, 1.3437739e-08,
+ -0.7613537, -7.000451e-08};
+
+} // namespace unidir_lstm_float
+
+class TestDataFloatUnidirectionalLSTM : public TestDataUnidirectionalLSTMBase<float>
+{
+public:
+ TestDataFloatUnidirectionalLSTM()
+ {
+ _input_data = unidir_lstm_float::input_data;
+ _reference_output_data = unidir_lstm_float::reference_output_data;
+ _test_kernel_model_circle = unidir_lstm_float::test_kernel_model_circle;
+ }
+
+ ~TestDataFloatUnidirectionalLSTM() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_UNIDIRECTIONAL_LSTM_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/unidirectional_lstm/QuantS8UnidirectionalLSTM.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/unidirectional_lstm/QuantS8UnidirectionalLSTM.h
new file mode 100644
index 000000000..d4bd798a3
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/unidirectional_lstm/QuantS8UnidirectionalLSTM.h
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_QUANT_S8_UNIDIRECTIONAL_LSTM_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_QUANT_S8_UNIDIRECTIONAL_LSTM_KERNEL_H
+
+#include "TestDataUnidirectionalLSTMBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace unidir_lstm_int8
+{
+/*
+ * UnidirectionalLSTM Kernel:
+ *
+ * Input(1, 20, 20)
+ * |
+ * UnidirectionalLSTM
+ * |
+ * Output(1, 20, 2)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x1c, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x54, 0x02, 0x00, 0x00, 0xd8, 0x0a, 0x00, 0x00, 0xf4, 0x0a, 0x00, 0x00,
+ 0x13, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x34, 0x02, 0x00, 0x00, 0x1c, 0x02, 0x00, 0x00,
+ 0xfc, 0x01, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, 0xec, 0x01, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00,
+ 0xc4, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00,
+ 0x2c, 0x01, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00,
+ 0x94, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x2e, 0xfe, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x0e, 0x00, 0x08, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
+ 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x31,
+ 0x2e, 0x30, 0x00, 0x00, 0x92, 0xfe, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x31, 0x2e, 0x31, 0x33, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x90, 0xfe, 0xff, 0xff, 0xb2, 0xfe, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xff, 0x7f, 0xff, 0x7f, 0xc2, 0xfe, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xd2, 0xfe, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
+ 0x7f, 0xdb, 0x47, 0xd4, 0x00, 0xba, 0x1c, 0x49, 0xd9, 0xb1, 0x98, 0xa7, 0x76, 0x4d, 0x90, 0xab,
+ 0x19, 0x5d, 0x72, 0xfa, 0xe1, 0x95, 0x07, 0x05, 0x63, 0xfb, 0x6e, 0x59, 0xd9, 0x0e, 0x94, 0x04,
+ 0x01, 0x72, 0x3b, 0x8e, 0x58, 0x4a, 0xd1, 0xd6, 0x06, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0xbd, 0x21, 0x0b, 0x84, 0xf4, 0xc6, 0x67, 0x3f, 0x19, 0xc2, 0x5f, 0x92,
+ 0x19, 0x4a, 0x9a, 0xef, 0xbb, 0x79, 0x45, 0x93, 0x09, 0x17, 0x50, 0xdd, 0x2e, 0x5c, 0xe3, 0x5f,
+ 0xc9, 0x81, 0xb9, 0x1a, 0x5e, 0x45, 0x84, 0xe1, 0xb4, 0xe3, 0x58, 0x1b, 0x3a, 0xff, 0xff, 0xff,
+ 0x04, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x03, 0xa1, 0x30, 0x2e, 0x08, 0x1d, 0x39, 0xe1,
+ 0xed, 0xea, 0x19, 0xc0, 0x86, 0xe4, 0x71, 0x50, 0xc6, 0x4f, 0x05, 0xbc, 0xf7, 0xdf, 0x93, 0xea,
+ 0x94, 0xbd, 0x00, 0x49, 0x2a, 0x2a, 0xd0, 0x5e, 0x06, 0x81, 0xdd, 0xe0, 0xaf, 0xf9, 0x71, 0x24,
+ 0x6e, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x9b, 0xf8, 0x5a, 0xaa,
+ 0x6c, 0x6a, 0x2f, 0x8a, 0x9f, 0xe1, 0x7e, 0x85, 0x81, 0xe1, 0xea, 0x6d, 0x89, 0x28, 0xd1, 0x49,
+ 0x82, 0x6b, 0x25, 0x48, 0x1a, 0xc6, 0xce, 0x0b, 0xcd, 0xd2, 0x24, 0x51, 0xf3, 0x48, 0xf6, 0x6f,
+ 0xe2, 0x5c, 0x36, 0x5b, 0xa2, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x7f, 0xd4, 0xbf, 0xc1, 0xb2, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xf6, 0x10, 0x7f, 0x09, 0xc2, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xf4, 0x81, 0x11, 0x1f, 0xd2, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x7f, 0x5f, 0x7e, 0x84, 0xc4, 0xff, 0xff, 0xff, 0xc8, 0xff, 0xff, 0xff, 0xea, 0xff, 0xff, 0xff,
+ 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x2c, 0x03, 0x00, 0x00, 0x2c, 0x03, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00,
+ 0xc8, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x41,
+ 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x09, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x15, 0x00, 0x00, 0x00, 0x18, 0x07, 0x00, 0x00, 0xb0, 0x06, 0x00, 0x00, 0x54, 0x06, 0x00, 0x00,
+ 0xf8, 0x05, 0x00, 0x00, 0x9c, 0x05, 0x00, 0x00, 0x40, 0x05, 0x00, 0x00, 0xe4, 0x04, 0x00, 0x00,
+ 0x88, 0x04, 0x00, 0x00, 0x2c, 0x04, 0x00, 0x00, 0xd0, 0x03, 0x00, 0x00, 0x74, 0x03, 0x00, 0x00,
+ 0x18, 0x03, 0x00, 0x00, 0xbc, 0x02, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0xe4, 0x01, 0x00, 0x00,
+ 0xac, 0x01, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
+ 0x84, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x4a, 0xf9, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x48, 0x00, 0x00, 0x00,
+ 0x3c, 0xf9, 0xff, 0xff, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x1d, 0x87, 0xfd, 0x3b, 0x19, 0x00, 0x00, 0x00, 0x53, 0x74, 0x61, 0x74, 0x65, 0x66, 0x75, 0x6c,
+ 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x43, 0x61, 0x6c, 0x6c, 0x3a,
+ 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x09, 0x50, 0x00, 0x00, 0x00, 0xb4, 0xf9, 0xff, 0xff, 0x18, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1d, 0x87, 0xfd, 0x3b, 0x23, 0x00, 0x00, 0x00,
+ 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e,
+ 0x5f, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69,
+ 0x61, 0x74, 0x65, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0xff, 0xff, 0xff,
+ 0x08, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x70, 0x75,
+ 0x74, 0x5f, 0x74, 0x6f, 0x5f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65,
+ 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x94, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+ 0x1a, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x65, 0x6c,
+ 0x6c, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x74, 0x6f,
+ 0x5f, 0x66, 0x6f, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64,
+ 0x69, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x70, 0x75,
+ 0x74, 0x5f, 0x74, 0x6f, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72,
+ 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0x40, 0x00, 0x00, 0x00, 0x04, 0xfb, 0xff, 0xff, 0x18, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x12, 0x00, 0x00, 0x00,
+ 0x74, 0x66, 0x6c, 0x2e, 0x70, 0x73, 0x65, 0x75, 0x64, 0x6f, 0x5f, 0x71, 0x63, 0x6f, 0x6e, 0x73,
+ 0x74, 0x31, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x07, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x00, 0x00, 0x74, 0xfb, 0xff, 0xff, 0x18, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1d, 0x87, 0xfd, 0x3b, 0x11, 0x00, 0x00, 0x00,
+ 0x74, 0x66, 0x6c, 0x2e, 0x70, 0x73, 0x65, 0x75, 0x64, 0x6f, 0x5f, 0x71, 0x63, 0x6f, 0x6e, 0x73,
+ 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0xe2, 0xfb, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x09, 0x38, 0x00, 0x00, 0x00, 0xd4, 0xfb, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x67, 0x21, 0x6d, 0x3b, 0x0f, 0x00, 0x00, 0x00, 0x61, 0x72, 0x69, 0x74,
+ 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x39, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x3a, 0xfc, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x38, 0x00, 0x00, 0x00,
+ 0x2c, 0xfc, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xec, 0x45, 0x69, 0x3b,
+ 0x0f, 0x00, 0x00, 0x00, 0x61, 0x72, 0x69, 0x74, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61,
+ 0x6e, 0x74, 0x38, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x92, 0xfc, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x09, 0x38, 0x00, 0x00, 0x00, 0x84, 0xfc, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0xb9, 0xbc, 0x68, 0x3b, 0x0f, 0x00, 0x00, 0x00, 0x61, 0x72, 0x69, 0x74,
+ 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x37, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xea, 0xfc, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x38, 0x00, 0x00, 0x00,
+ 0xdc, 0xfc, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3f, 0xac, 0x6e, 0x3b,
+ 0x0f, 0x00, 0x00, 0x00, 0x61, 0x72, 0x69, 0x74, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61,
+ 0x6e, 0x74, 0x36, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x42, 0xfd, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x09, 0x38, 0x00, 0x00, 0x00, 0x34, 0xfd, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x24, 0x56, 0x7e, 0x3b, 0x0f, 0x00, 0x00, 0x00, 0x61, 0x72, 0x69, 0x74,
+ 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x33, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x9a, 0xfd, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x38, 0x00, 0x00, 0x00,
+ 0x8c, 0xfd, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0xa6, 0x65, 0x3b,
+ 0x0f, 0x00, 0x00, 0x00, 0x61, 0x72, 0x69, 0x74, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61,
+ 0x6e, 0x74, 0x32, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0xf2, 0xfd, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x09, 0x38, 0x00, 0x00, 0x00, 0xe4, 0xfd, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x38, 0x10, 0xb8, 0x3b, 0x0f, 0x00, 0x00, 0x00, 0x61, 0x72, 0x69, 0x74,
+ 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x31, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4a, 0xfe, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x38, 0x00, 0x00, 0x00,
+ 0x3c, 0xfe, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x7d, 0x3b,
+ 0x0e, 0x00, 0x00, 0x00, 0x61, 0x72, 0x69, 0x74, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61,
+ 0x6e, 0x74, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0xa2, 0xfe, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x3c, 0x00, 0x00, 0x00, 0x94, 0xfe, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x08, 0x38, 0xa5, 0x3a, 0x10, 0x00, 0x00, 0x00, 0x61, 0x72, 0x69, 0x74,
+ 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x34, 0x32, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xfa, 0xfe, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x3c, 0x00, 0x00, 0x00,
+ 0xec, 0xfe, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x1c, 0xa1, 0x3a,
+ 0x10, 0x00, 0x00, 0x00, 0x61, 0x72, 0x69, 0x74, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61,
+ 0x6e, 0x74, 0x34, 0x31, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x52, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x3c, 0x00, 0x00, 0x00, 0x44, 0xff, 0xff, 0xff, 0x18, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xb4, 0x26, 0xa4, 0x3a, 0x0f, 0x00, 0x00, 0x00,
+ 0x61, 0x72, 0x69, 0x74, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x34, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xaa, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x38, 0x00, 0x00, 0x00,
+ 0x9c, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x21, 0x7b, 0xa1, 0x3a,
+ 0x0f, 0x00, 0x00, 0x00, 0x61, 0x72, 0x69, 0x74, 0x68, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61,
+ 0x6e, 0x74, 0x35, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
+ 0x50, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0xa3, 0x36, 0xb1, 0x3e,
+ 0x19, 0x00, 0x00, 0x00, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x66, 0x61,
+ 0x75, 0x6c, 0x74, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x31, 0x3a, 0x30, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c,
+ 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<int8_t> input_data = {
+ -19, -32, -10, -8, -23, -21, -19, -8, -10, -19, -35, -28, -19, -19, -8, -17, -17, -19, 5,
+ -19, -30, -21, -30, -8, -28, -37, -30, -17, -10, -28, -30, -17, -19, -21, -19, -19, 12, -6,
+ -10, -8, -10, -8, -21, -19, -30, -19, -8, -6, -24, -17, -8, -8, -19, -10, -28, -48, -10,
+ -19, -19, -17, 1, -30, -21, -17, 12, -19, -1, -19, -17, -1, -30, -19, -19, -28, -1, -10,
+ -32, -19, -19, -21, -19, -39, -8, -6, -12, -21, -28, -19, -15, -26, -19, -17, -19, -19, -19,
+ -19, -28, -19, -17, -30, 3, -10, -28, -30, -10, -19, -19, -21, -8, -28, -19, -19, -28, -17,
+ -19, -19, -19, -17, -17, -8, -12, -19, -19, -19, -30, -19, -8, -10, -28, -19, -30, -28, -26,
+ -8, -19, -19, -10, -30, -30, -39, -21, -39, -19, 1, -8, -19, -21, -10, -8, -10, -30, -30,
+ -19, -30, -19, -21, -19, -19, -21, -41, -17, -41, -19, -10, -19, -10, -30, -19, 3, -6, -23,
+ -28, -23, -10, -19, -10, -19, 1, -19, -30, -10, -8, -17, -19, -17, -26, -19, -19, -19, -26,
+ -23, -28, -19, -28, -12, -19, -30, -19, -19, -17, -28, -19, -28, -30, -8, -15, -1, -8, -19,
+ -19, -19, -21, -17, -8, -19, -21, -28, -30, 3, -28, -19, -19, -10, -19, -6, -28, -19, -17,
+ -46, -19, -19, -19, -10, 3, -19, -19, -19, -19, -19, -17, -21, -32, -19, -30, -19, -19, -19,
+ -17, -24, -10, -28, -8, -32, -10, -26, -8, -30, -17, -19, -17, -17, -8, -19, 3, -1, -30,
+ -19, -15, -19, -37, -19, -19, -19, -19, -19, -21, -8, -21, -19, -50, -30, -10, -6, -19, -19,
+ -24, -21, -17, -10, -17, -19, -19, -19, -17, -15, -21, -50, -19, -1, -10, -19, -19, -19, -39,
+ -28, -17, 10, -19, 1, 1, -8, -15, -19, -23, -10, -8, -19, 3, -19, 3, -19, -30, -23,
+ -48, -8, -8, -28, -10, -37, -19, -15, -19, -26, -10, -1, -10, -19, -19, -32, -17, -30, -17,
+ -21, -32, -19, 5, -21, -12, -1, -19, -10, -30, -19, -41, -17, -23, -10, -26, -28, -30, -30,
+ -21, -19, -10, -10, -19, -8, -12, -19, -19, 1, -19, -1, -10, -19, -56, -21, -10, -41, -17,
+ -28, -10, -25, -30, -21, -48, -30, -30, -21, -19, -19, -19, -30, -8, 12, -10, -8, -6, -28,
+ -17};
+
+const std::vector<int8_t> reference_output_data = {
+ 0, 85, 0, 98, 0, 66, 29, -7, 13, -95, -5, -90, 0, -7, 0, -4, 4, -74, 32, -96,
+ 21, -86, 7, -98, 48, -89, 0, -98, 90, -97, 96, 82, 46, -35, 32, -1, -2, -85, -2, -97};
+
+} // namespace unidir_lstm_int8
+
+class TestDataInt8UnidirectionalLSTM : public TestDataUnidirectionalLSTMBase<int8_t>
+{
+public:
+ TestDataInt8UnidirectionalLSTM()
+ {
+ _input_data = unidir_lstm_int8::input_data;
+ _reference_output_data = unidir_lstm_int8::reference_output_data;
+ _test_kernel_model_circle = unidir_lstm_int8::test_kernel_model_circle;
+ }
+
+ ~TestDataInt8UnidirectionalLSTM() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_QUANT_S8_UNIDIRECTIONAL_LSTM_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/unidirectional_lstm/TestDataUnidirectionalLSTMBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/unidirectional_lstm/TestDataUnidirectionalLSTMBase.h
new file mode 100644
index 000000000..942265517
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/unidirectional_lstm/TestDataUnidirectionalLSTMBase.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_UNIDIRECTIONAL_LSTM_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_UNIDIRECTIONAL_LSTM_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataUnidirectionalLSTMBase : public TestDataBase<T>
+{
+public:
+ TestDataUnidirectionalLSTMBase() = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_UNIDIRECTIONAL_LSTM_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/while/NegWhileKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/while/NegWhileKernel.h
new file mode 100644
index 000000000..d193fbfa8
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/while/NegWhileKernel.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_WHILE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_WHILE_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+namespace neg_while_kernel
+{
+/*
+ * While Kernel with wrong output type for Cond Graph (should be boolean but using int32):
+ * Main graph:
+ * Input(1)
+ * |
+ * While
+ * |
+ * Output(1)
+ *
+ * Cond graph:
+ * CInput(1)
+ * |
+ * Less (Const = 10)
+ * |
+ * COutput(1) - int32, but should be bool
+ *
+ * Body Graph:
+ * BInput(1)
+ * |
+ * Add (Const = 1)
+ * |
+ * BOutput(1)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x7c, 0x00, 0x00, 0x00, 0x78, 0x03, 0x00, 0x00, 0xb0, 0x03, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xe2, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x94, 0xfc, 0xff, 0xff, 0x04, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xb8, 0xfc, 0xff, 0xff, 0xbc, 0xfc, 0xff, 0xff,
+ 0xc0, 0xfc, 0xff, 0xff, 0xc4, 0xfc, 0xff, 0xff, 0xc8, 0xfc, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00,
+ 0x10, 0x02, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0xfe, 0xff, 0xff,
+ 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x48, 0x49, 0x4c, 0x45, 0x5f, 0x42, 0x4f,
+ 0x44, 0x59, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0xfd, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xd0, 0xfd, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x62, 0x6f, 0x66, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0xf8, 0xfd, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x62, 0x69, 0x66, 0x6d, 0x33, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x1c, 0xfe, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x62, 0x69, 0x66, 0x6d,
+ 0x31, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0xff, 0xff, 0xff,
+ 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+ 0x5c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x48, 0x49, 0x4c, 0x45, 0x5f, 0x43, 0x4f,
+ 0x4e, 0x44, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x24, 0xfe, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xc4, 0xfe, 0xff, 0xff,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x66, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x63, 0x69, 0x66, 0x6d,
+ 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x63, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x70, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x4d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xdc, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf4, 0xff, 0xff, 0xff,
+ 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+} // namespace neg_while_kernel
+
+class NegTestDataWhileKernel : public NegTestDataBase
+{
+public:
+ NegTestDataWhileKernel()
+ {
+ _test_kernel_model_circle = neg_while_kernel::test_kernel_model_circle;
+ }
+
+ ~NegTestDataWhileKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_WHILE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/while/WhileKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/while/WhileKernel.h
new file mode 100644
index 000000000..73c27cde9
--- /dev/null
+++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/while/WhileKernel.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_WHILE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_WHILE_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+namespace while_kernel
+{
+/*
+ * While Kernel:
+ * Main graph:
+ * Input(1)
+ * |
+ * While
+ * |
+ * Output(1)
+ *
+ * Cond graph:
+ * CInput(1)
+ * |
+ * Less (Const = 10)
+ * |
+ * COutput(1)
+ *
+ * Body Graph:
+ * BInput(1)
+ * |
+ * Add (Const = 1)
+ * |
+ * BOutput(1)
+ */
+const unsigned char test_kernel_model_circle[] = {
+ 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x7c, 0x00, 0x00, 0x00, 0x78, 0x03, 0x00, 0x00, 0xb0, 0x03, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xe2, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x94, 0xfc, 0xff, 0xff, 0x04, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xb8, 0xfc, 0xff, 0xff, 0xbc, 0xfc, 0xff, 0xff,
+ 0xc0, 0xfc, 0xff, 0xff, 0xc4, 0xfc, 0xff, 0xff, 0xc8, 0xfc, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00,
+ 0x10, 0x02, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0xfe, 0xff, 0xff,
+ 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x48, 0x49, 0x4c, 0x45, 0x5f, 0x42, 0x4f,
+ 0x44, 0x59, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x30, 0xfd, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xd0, 0xfd, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x62, 0x6f, 0x66, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0xf8, 0xfd, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x62, 0x69, 0x66, 0x6d, 0x33, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x1c, 0xfe, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x62, 0x69, 0x66, 0x6d,
+ 0x31, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0xff, 0xff, 0xff,
+ 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+ 0x5c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x48, 0x49, 0x4c, 0x45, 0x5f, 0x43, 0x4f,
+ 0x4e, 0x44, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x24, 0xfe, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xc4, 0xfe, 0xff, 0xff,
+ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x66, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x63, 0x69, 0x66, 0x6d,
+ 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x63, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x70, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x4d, 0x61, 0x69, 0x6e,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xdc, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf4, 0xff, 0xff, 0xff,
+ 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d,
+ 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00};
+
+const std::vector<int32_t> input_data = {35};
+
+const std::vector<int32_t> reference_output_data = {35};
+} // namespace while_kernel
+
+template <typename T> class TestDataWhileKernel : public TestDataBase<T>
+{
+public:
+ TestDataWhileKernel()
+ {
+ _input_data = while_kernel::input_data;
+ _reference_output_data = while_kernel::reference_output_data;
+ _test_kernel_model_circle = while_kernel::test_kernel_model_circle;
+ }
+
+ ~TestDataWhileKernel() override = default;
+
+ const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+ const std::vector<T> &get_input_data_by_index(int i) override final
+ {
+ switch (i)
+ {
+ case 0:
+ return _input_data;
+ default:
+ assert(false && "Wrong input index");
+ }
+ }
+
+ const std::vector<T> &get_output_data_by_index(int i) override final
+ {
+ assert(i == 0);
+ return _reference_output_data;
+ }
+
+protected:
+ std::vector<T> _input_data;
+ std::vector<T> _reference_output_data;
+ const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_WHILE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALArgMax.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALArgMax.h
deleted file mode 100644
index 84147b205..000000000
--- a/onert-micro/luci-interpreter/pal/cmsisnn/PALArgMax.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_ARGMAX_H
-#define LUCI_INTERPRETER_PAL_ARGMAX_H
-
-#include <tensorflow/lite/kernels/internal/reference/arg_min_max.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T1, typename T2, typename T3>
-static inline void ArgMinMax(const tflite::RuntimeShape &input1_shape, const T1 *input1_data,
- const T2 *axis, const tflite::RuntimeShape &output_shape,
- T3 *output_data, const std::greater<T1> cmp)
-{
- tflite::reference_ops::ArgMinMax(input1_shape, input1_data, axis, output_shape, output_data, cmp);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_ARGMAX_H
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALAveragePool2d.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALAveragePool2d.h
deleted file mode 100644
index 79ed587b8..000000000
--- a/onert-micro/luci-interpreter/pal/cmsisnn/PALAveragePool2d.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_AVERAGEPOOL2D_H
-#define LUCI_INTERPRETER_PAL_AVERAGEPOOL2D_H
-
-#include <tensorflow/lite/kernels/internal/reference/integer_ops/pooling.h>
-#include <tensorflow/lite/kernels/internal/reference/pooling.h>
-#include <arm_nn_types.h>
-#include <arm_nnfunctions.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void AveragePool(const tflite::PoolParams &params,
- const tflite::RuntimeShape &input_shape, const T *input_data,
- const tflite::RuntimeShape &output_shape, T *output_data,
- const tflite::RuntimeShape &scratchpad_shape, T *scratchpad_data)
-{
- {
- // MARK: At this moment this operation is not supported
- assert(false && "AveragePool NYI");
- (void)params;
- (void)input_shape;
- (void)input_data;
- (void)output_shape;
- (void)output_data;
- (void)scratchpad_shape;
- (void)scratchpad_data;
- }
-}
-
-template <>
-inline void AveragePool<int8_t>(const tflite::PoolParams &params,
- const tflite::RuntimeShape &input_shape, const int8_t *input_data,
- const tflite::RuntimeShape &output_shape, int8_t *output_data,
- const tflite::RuntimeShape &scratchpad_shape,
- int8_t *scratchpad_data)
-{
- assert(input_shape.DimensionsCount() == 4);
- assert(output_shape.DimensionsCount() == 4);
- assert(scratchpad_data != nullptr);
-
- const int32_t batches = tflite::MatchingDim(input_shape, 0, output_shape, 0);
- assert(batches == 1);
-
- const int depth = tflite::MatchingDim(input_shape, 3, output_shape, 3);
-
- cmsis_nn_dims input_dims;
- input_dims.n = 1;
- input_dims.h = input_shape.Dims(1);
- input_dims.w = input_shape.Dims(2);
- input_dims.c = depth;
-
- cmsis_nn_dims output_dims;
- output_dims.n = 1;
- output_dims.h = output_shape.Dims(1);
- output_dims.w = output_shape.Dims(2);
- output_dims.c = depth;
-
- cmsis_nn_pool_params pool_params;
- pool_params.stride.h = params.stride_height;
- pool_params.stride.w = params.stride_width;
- pool_params.padding.h = params.padding_values.height;
- pool_params.padding.w = params.padding_values.width;
- pool_params.activation.min = params.quantized_activation_min;
- pool_params.activation.max = params.quantized_activation_max;
-
- cmsis_nn_dims filter_dims;
- filter_dims.n = 1;
- filter_dims.h = params.filter_height;
- filter_dims.w = params.filter_width;
- filter_dims.c = 1;
-
- cmsis_nn_context ctx;
- ctx.buf = scratchpad_data;
- ctx.size = scratchpad_shape.Dims(0);
- auto res = arm_avgpool_s8(&ctx, &pool_params, &input_dims, input_data, &filter_dims, &output_dims,
- output_data);
- assert(res == ARM_MATH_SUCCESS);
-}
-
-static inline void SetupScratchpadTensor(luci_interpreter::Tensor *scratchpad,
- const luci_interpreter::DataType &input_data_type,
- const tflite::RuntimeShape &input_shape,
- const tflite::RuntimeShape &output_shape)
-
-{
- if (input_data_type == luci_interpreter::DataType::S8)
- {
- assert(input_shape.DimensionsCount() == 4);
- assert(output_shape.DimensionsCount() == 4);
-
- const int32_t output_width = output_shape.Dims(2);
- const int32_t depth = tflite::MatchingDim(input_shape, 3, output_shape, 3);
-
- const int32_t buf_size = arm_avgpool_s8_get_buffer_size(output_width, depth);
- auto data_type_size = static_cast<int32_t>(luci_interpreter::getDataTypeSize(input_data_type));
-
- luci_interpreter::Shape scratchpad_shape{buf_size * data_type_size};
- scratchpad->resize(scratchpad_shape);
- }
- else
- {
- scratchpad->set_allocatable(false);
- }
-}
-
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_AVERAGEPOOL2D_H
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALBatchToSpaceND.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALBatchToSpaceND.h
deleted file mode 100644
index 9ba31960a..000000000
--- a/onert-micro/luci-interpreter/pal/cmsisnn/PALBatchToSpaceND.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_BATCHTOSPACEND_H
-#define LUCI_INTERPRETER_PAL_BATCHTOSPACEND_H
-
-#include <tensorflow/lite/kernels/internal/reference/batch_to_space_nd.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void
-BatchToSpaceND(const tflite::RuntimeShape &unextended_input1_shape, const T *input1_data,
- const tflite::RuntimeShape &unextended_input2_shape, const int32 *block_shape_data,
- const tflite::RuntimeShape &unextended_input3_shape, const int32 *crops_data,
- const tflite::RuntimeShape &unextended_output_shape, T *output_data)
-{
- tflite::reference_ops::BatchToSpaceND(
- unextended_input1_shape, input1_data, unextended_input2_shape, block_shape_data,
- unextended_input3_shape, crops_data, unextended_output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_BATCHTOSPACEND_H
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALConv2d.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALConv2d.h
index 7ec64a768..bd47a88cb 100644
--- a/onert-micro/luci-interpreter/pal/cmsisnn/PALConv2d.h
+++ b/onert-micro/luci-interpreter/pal/cmsisnn/PALConv2d.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALDepthToSpace.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALDepthToSpace.h
deleted file mode 100644
index ce5be4352..000000000
--- a/onert-micro/luci-interpreter/pal/cmsisnn/PALDepthToSpace.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_DEPTHTOSPACE_H
-#define LUCI_INTERPRETER_PAL_DEPTHTOSPACE_H
-
-#include <tensorflow/lite/kernels/internal/reference/depth_to_space.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void DepthToSpace(const tflite::DepthToSpaceParams &op_params,
- const tflite::RuntimeShape &unextended_input_shape,
- const T *input_data,
- const tflite::RuntimeShape &unextended_output_shape, T *output_data)
-{
- tflite::reference_ops::DepthToSpace(op_params, unextended_input_shape, input_data,
- unextended_output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_DEPTHTOSPACE_H
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALDepthwiseConv2d.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALDepthwiseConv2d.h
deleted file mode 100644
index 5f5e4dd8e..000000000
--- a/onert-micro/luci-interpreter/pal/cmsisnn/PALDepthwiseConv2d.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_DEPTHWISECONV2D_H
-#define LUCI_INTERPRETER_PAL_DEPTHWISECONV2D_H
-
-#include <tensorflow/lite/kernels/internal/reference/depthwiseconv_float.h>
-#include <tensorflow/lite/kernels/internal/reference/depthwiseconv_uint8.h>
-#include <tensorflow/lite/kernels/internal/reference/integer_ops/depthwise_conv.h>
-#include <arm_nnfunctions.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void
-DepthwiseConvPerChannel(const tflite::DepthwiseParams &params, const int32_t *output_multiplier,
- const int32_t *output_shift, const tflite::RuntimeShape &input_shape,
- const T *input_data, const tflite::RuntimeShape &filter_shape,
- const T *filter_data, const tflite::RuntimeShape &bias_shape,
- const int32_t *bias_data, const tflite::RuntimeShape &output_shape,
- T *output_data, const tflite::RuntimeShape &scratchpad_shape,
- T *scratchpad_data)
-{
- {
- // MARK: At this moment this operation is not supported
- assert(false && "DepthwiseConvPerChannel NYI");
- (void)params;
- (void)output_multiplier;
- (void)output_shift;
- (void)input_shape;
- (void)output_data;
- (void)input_data;
- (void)filter_shape;
- (void)filter_data;
- (void)bias_shape;
- (void)bias_data;
- (void)output_shape;
- (void)output_data;
- (void)scratchpad_shape;
- (void)scratchpad_data;
- }
-}
-
-template <>
-inline void DepthwiseConvPerChannel<int8_t>(
- const tflite::DepthwiseParams &params, const int32_t *output_multiplier,
- const int32_t *output_shift, const tflite::RuntimeShape &input_shape, const int8_t *input_data,
- const tflite::RuntimeShape &filter_shape, const int8_t *filter_data,
- const tflite::RuntimeShape &bias_shape, const int32_t *bias_data,
- const tflite::RuntimeShape &output_shape, int8_t *output_data,
- const tflite::RuntimeShape &scratchpad_shape, int8_t *scratchpad_data)
-{
- if (scratchpad_data)
- {
- cmsis_nn_dw_conv_params dw_conv_params;
- dw_conv_params.dilation.h = params.dilation_height_factor;
- dw_conv_params.dilation.w = params.dilation_width_factor;
- assert(dw_conv_params.dilation.h == 1);
- assert(dw_conv_params.dilation.w == 1);
-
- dw_conv_params.input_offset = params.input_offset;
- dw_conv_params.output_offset = params.output_offset;
- dw_conv_params.stride.h = params.stride_height;
- dw_conv_params.stride.w = params.stride_width;
- dw_conv_params.padding.h = params.padding_values.height;
- dw_conv_params.padding.w = params.padding_values.width;
-
- dw_conv_params.activation.min = params.quantized_activation_min;
- dw_conv_params.activation.max = params.quantized_activation_max;
- dw_conv_params.ch_mult = params.depth_multiplier;
-
- cmsis_nn_per_channel_quant_params quant_params;
- int32_t output_multiplier = params.output_multiplier;
- int32_t output_shift = params.output_shift;
-
- quant_params.multiplier = &output_multiplier;
- quant_params.shift = &output_shift;
-
- assert(dw_conv_params.activation.min <= dw_conv_params.activation.max);
- const int batch_size = tflite::MatchingDim(input_shape, 0, output_shape, 0);
- const int output_depth = tflite::MatchingDim(filter_shape, 3, output_shape, 3);
- if (bias_data)
- {
- assert(bias_shape.FlatSize() == output_depth);
- }
-
- cmsis_nn_dims input_dims;
- input_dims.n = batch_size;
- input_dims.h = input_shape.Dims(1);
- input_dims.w = input_shape.Dims(2);
- input_dims.c = input_shape.Dims(3);
-
- cmsis_nn_dims filter_dims;
- filter_dims.n = filter_shape.Dims(0);
- filter_dims.h = filter_shape.Dims(1);
- filter_dims.w = filter_shape.Dims(2);
- filter_dims.c = output_depth;
-
- cmsis_nn_dims bias_dims;
- bias_dims.n = 1;
- bias_dims.h = 1;
- bias_dims.w = 1;
- bias_dims.c = output_depth;
-
- cmsis_nn_dims output_dims;
- output_dims.n = batch_size;
- output_dims.h = output_shape.Dims(1);
- output_dims.w = output_shape.Dims(2);
- output_dims.c = output_depth;
-
- cmsis_nn_context ctx;
- ctx.buf = scratchpad_data;
- ctx.size = scratchpad_shape.Dims(0);
-
- auto res = arm_depthwise_conv_wrapper_s8(&ctx, &dw_conv_params, &quant_params, &input_dims,
- input_data, &filter_dims, filter_data, &bias_dims,
- bias_data, &output_dims, output_data);
- assert(res == ARM_MATH_SUCCESS);
- }
- else
- {
- tflite::reference_integer_ops::DepthwiseConvPerChannel(
- params, output_multiplier, output_shift, input_shape, input_data, filter_shape, filter_data,
- bias_shape, bias_data, output_shape, output_data);
- }
-}
-
-static inline void SetupScratchpadTensor(luci_interpreter::Tensor *scratchpad,
- const tflite::DepthwiseParams &params,
- const luci_interpreter::DataType &input_data_type,
- const tflite::RuntimeShape &input_shape,
- const tflite::RuntimeShape &filter_shape,
- const tflite::RuntimeShape &output_shape)
-{
- cmsis_nn_dw_conv_params dw_conv_params;
- dw_conv_params.dilation.h = params.dilation_height_factor;
- dw_conv_params.dilation.w = params.dilation_width_factor;
-
- if (input_data_type == luci_interpreter::DataType::S8 && dw_conv_params.dilation.h == 1 &&
- dw_conv_params.dilation.w == 1)
- {
- const int batch_size = tflite::MatchingDim(input_shape, 0, output_shape, 0);
- const int output_depth = tflite::MatchingDim(filter_shape, 3, output_shape, 3);
-
- cmsis_nn_dims input_dims;
- input_dims.n = batch_size;
- input_dims.h = input_shape.Dims(1);
- input_dims.w = input_shape.Dims(2);
- input_dims.c = input_shape.Dims(3);
-
- cmsis_nn_dims filter_dims;
- filter_dims.n = filter_shape.Dims(0);
- filter_dims.h = filter_shape.Dims(1);
- filter_dims.w = filter_shape.Dims(2);
- filter_dims.c = output_depth;
-
- cmsis_nn_dims output_dims;
- output_dims.n = batch_size;
- output_dims.h = output_shape.Dims(1);
- output_dims.w = output_shape.Dims(2);
- output_dims.c = output_depth;
-
- const int32_t buf_size = arm_depthwise_conv_wrapper_s8_get_buffer_size(
- &dw_conv_params, &input_dims, &filter_dims, &output_dims);
-
- auto data_type_size = static_cast<int32_t>(luci_interpreter::getDataTypeSize(input_data_type));
-
- luci_interpreter::Shape scratchpad_shape{buf_size * data_type_size};
- scratchpad->resize(scratchpad_shape);
- }
- else
- {
- scratchpad->set_allocatable(false);
- }
-}
-
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_DEPTHWISECONV2D_H
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALDequantize.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALDequantize.h
deleted file mode 100644
index a11abef4b..000000000
--- a/onert-micro/luci-interpreter/pal/cmsisnn/PALDequantize.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_DEQUANTIZE_H
-#define LUCI_INTERPRETER_PAL_DEQUANTIZE_H
-
-#include "tensorflow/lite/kernels/internal/reference/integer_ops/dequantize.h"
-#include "PALreference_ops.h"
-
-namespace luci_interpreter_pal
-{
-
-template <typename T>
-static inline void Dequantize(tflite::DequantizationParams &params,
- const tflite::RuntimeShape &input_shape, const T *input_data,
- const tflite::RuntimeShape &output_shape, float *output_data)
-{
- tflite::reference_integer_ops::Dequantize<T>(params, input_shape, input_data, output_shape,
- output_data);
-}
-
-static inline void Dequantize(tflite::DequantizationParams &params,
- const tflite::RuntimeShape &input_shape, const uint8_t *input_data,
- const tflite::RuntimeShape &output_shape, float *output_data)
-{
- tflite::reference_ops::Dequantize(params, input_shape, input_data, output_shape, output_data);
-}
-
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_DEQUANTIZE_H
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALFullyConnected.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALFullyConnected.h
index 87e29ce64..32e905761 100644
--- a/onert-micro/luci-interpreter/pal/cmsisnn/PALFullyConnected.h
+++ b/onert-micro/luci-interpreter/pal/cmsisnn/PALFullyConnected.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALL2Normalize.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALL2Normalize.h
deleted file mode 100644
index 16bc4ae8a..000000000
--- a/onert-micro/luci-interpreter/pal/cmsisnn/PALL2Normalize.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_L2NORMALIZE_H
-#define LUCI_INTERPRETER_PAL_L2NORMALIZE_H
-
-#include <tensorflow/lite/kernels/internal/reference/l2normalization.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void L2Normalization(const tflite::L2NormalizationParams &op_params,
- const tflite::RuntimeShape &input_shape, const T *input_data,
- const tflite::RuntimeShape &output_shape, T *output_data)
-{
- tflite::reference_ops::L2Normalization(op_params, input_shape, input_data, output_shape,
- output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_L2NORMALIZE_H
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALL2Pool2D.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALL2Pool2D.h
index aa3924e4c..38a302fc6 100644
--- a/onert-micro/luci-interpreter/pal/cmsisnn/PALL2Pool2D.h
+++ b/onert-micro/luci-interpreter/pal/cmsisnn/PALL2Pool2D.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALLeakyRelu.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALLeakyRelu.h
deleted file mode 100644
index 97daddc20..000000000
--- a/onert-micro/luci-interpreter/pal/cmsisnn/PALLeakyRelu.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_LEAKYRELU_H
-#define LUCI_INTERPRETER_PAL_LEAKYRELU_H
-
-#include <tensorflow/lite/kernels/internal/reference/leaky_relu.h>
-
-namespace luci_interpreter_pal
-{
-static inline void LeakyRelu(const tflite::LeakyReluParams &params,
- const tflite::RuntimeShape &input_shape, const float *input_data,
- const tflite::RuntimeShape &output_shape, float *output_data)
-{
- tflite::reference_ops::LeakyRelu(params, input_shape, input_data, output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_LEAKYRELU_H
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALMul.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALMul.h
index e98d8a25f..347a97a83 100644
--- a/onert-micro/luci-interpreter/pal/cmsisnn/PALMul.h
+++ b/onert-micro/luci-interpreter/pal/cmsisnn/PALMul.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALQuantize.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALQuantize.h
deleted file mode 100644
index 5d9ea5188..000000000
--- a/onert-micro/luci-interpreter/pal/cmsisnn/PALQuantize.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_QUANTIZE_H
-#define LUCI_INTERPRETER_PAL_QUANTIZE_H
-
-#include "PALreference_ops.h"
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void Quantize(tflite::QuantizationParams &params,
- const tflite::RuntimeShape &input_shape, const float *input_data,
- const tflite::RuntimeShape &output_shape, T *output_data)
-{
- tflite::reference_ops::AffineQuantize(params, input_shape, input_data, output_shape, output_data);
-}
-
-template <typename Input, typename Output>
-static inline void Requantize(const Input *input_data, int32_t size,
- int32_t effective_scale_multiplier, int32_t effective_scale_shift,
- int32_t input_zero_point, int32_t output_zero_point,
- Output *output_data)
-{
- tflite::reference_ops::Requantize(input_data, size, effective_scale_multiplier,
- effective_scale_shift, input_zero_point, output_zero_point,
- output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_QUANTIZE_H
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALResizeBilinear.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALResizeBilinear.h
deleted file mode 100644
index 91c28ef6b..000000000
--- a/onert-micro/luci-interpreter/pal/cmsisnn/PALResizeBilinear.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_RESIZEBILINEAR_H
-#define LUCI_INTERPRETER_PAL_RESIZEBILINEAR_H
-
-#include <tensorflow/lite/kernels/internal/reference/resize_bilinear.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void
-ResizeBilinear(const tflite::ResizeBilinearParams &op_params,
- const tflite::RuntimeShape &unextended_input_shape, const T *input_data,
- const tflite::RuntimeShape &output_size_shape, const int32 *output_size_data,
- const tflite::RuntimeShape &unextended_output_shape, T *output_data)
-{
- tflite::reference_ops::ResizeBilinear(op_params, unextended_input_shape, input_data,
- output_size_shape, output_size_data,
- unextended_output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_RESIZEBILINEAR_H
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALResizeNearestNeighbor.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALResizeNearestNeighbor.h
deleted file mode 100644
index 688eea3fc..000000000
--- a/onert-micro/luci-interpreter/pal/cmsisnn/PALResizeNearestNeighbor.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_RESIZENEARESTNEIGHBOR_H
-#define LUCI_INTERPRETER_PAL_RESIZENEARESTNEIGHBOR_H
-
-#include <tensorflow/lite/kernels/internal/reference/resize_nearest_neighbor.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void
-ResizeNearestNeighbor(const tflite::ResizeNearestNeighborParams &op_params,
- const tflite::RuntimeShape &unextended_input_shape, const T *input_data,
- const tflite::RuntimeShape &output_size_shape, const int32 *output_size_data,
- const tflite::RuntimeShape &unextended_output_shape, T *output_data)
-{
- tflite::reference_ops::ResizeNearestNeighbor(op_params, unextended_input_shape, input_data,
- output_size_shape, output_size_data,
- unextended_output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_RESIZENEARESTNEIGHBOR_H
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALSVDF.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALSVDF.h
deleted file mode 100644
index c1f096c65..000000000
--- a/onert-micro/luci-interpreter/pal/cmsisnn/PALSVDF.h
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2020 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_SVDF_H
-#define LUCI_INTERPRETER_PAL_SVDF_H
-
-#include <arm_nn_types.h>
-#include <arm_nnfunctions.h>
-
-namespace luci_interpreter_pal
-{
-static inline void
-IntegerSVDF(const TfLiteSVDFParams &params, const tflite::RuntimeShape &input_shape,
- const int8_t *input_data, const tflite::RuntimeShape &weight_feature_shape,
- const int8_t *weight_feature_data, const tflite::RuntimeShape &weight_time_shape,
- const int16_t *weight_time_data, const tflite::RuntimeShape &bias_shape,
- const int32_t *bias_data, int16_t *activation_state_data,
- const tflite::RuntimeShape &output_shape, int8_t *output_data, int32_t *scratchpad_data,
- int32_t *output_temp_data, int32_t scale_1_a, int scale_1_b, int32_t scale_2_a,
- int scale_2_b, int32_t input_zp, int32_t output_zp)
-{
- const int32_t rank = params.rank;
- const int32_t batch_size = input_shape.Dims(0);
- const int32_t num_filters = weight_feature_shape.Dims(0);
- const int32_t memory_size = weight_time_shape.Dims(1);
-
- cmsis_nn_dims input_dims;
- input_dims.n = input_shape.Dims(0);
- input_dims.h = input_shape.Dims(1);
-
- cmsis_nn_dims weights_feature_dims;
- weights_feature_dims.n = weight_feature_shape.Dims(0);
- weights_feature_dims.h = weight_feature_shape.Dims(1);
-
- cmsis_nn_dims weights_time_dims;
- weights_time_dims.n = weight_time_shape.Dims(0);
- weights_time_dims.h = weight_time_shape.Dims(1);
-
- cmsis_nn_dims bias_dims;
- bias_dims.n = bias_shape.Dims(0);
-
- cmsis_nn_dims state_dims;
- state_dims.n = batch_size;
- state_dims.h = memory_size * num_filters;
-
- cmsis_nn_dims output_dims;
- output_dims.n = output_shape.Dims(0);
- output_dims.h = output_shape.Dims(1);
-
- cmsis_nn_svdf_params svdf_params;
- svdf_params.rank = params.rank;
- svdf_params.input_offset = input_zp;
- svdf_params.output_offset = output_zp;
-
- svdf_params.input_activation.min = INT16_MIN;
- svdf_params.input_activation.max = INT16_MAX;
-
- svdf_params.output_activation.min = INT8_MIN;
- svdf_params.output_activation.max = INT8_MAX;
-
- cmsis_nn_per_tensor_quant_params in_quant_params;
- in_quant_params.multiplier = scale_1_a;
- in_quant_params.shift = scale_1_b;
-
- cmsis_nn_per_tensor_quant_params out_quant_params;
- out_quant_params.multiplier = scale_2_a;
- out_quant_params.shift = scale_2_b;
-
- cmsis_nn_context scratch_ctx;
- scratch_ctx.buf = scratchpad_data;
-
- cmsis_nn_context scratch_output_ctx;
- scratch_output_ctx.buf = output_temp_data;
-
- arm_svdf_s8(&scratch_ctx, &scratch_output_ctx, &svdf_params, &in_quant_params, &out_quant_params,
- &input_dims, input_data, &state_dims, activation_state_data, &weights_feature_dims,
- weight_feature_data, &weights_time_dims, weight_time_data, &bias_dims, bias_data,
- &output_dims, output_data);
-}
-static inline void
-FloatSVDF(const TfLiteSVDFParams &params, const tflite::RuntimeShape &input_shape,
- const float *input_data, const tflite::RuntimeShape &weight_feature_shape,
- const float *weight_feature_data, const tflite::RuntimeShape &weight_time_shape,
- const float *weight_time_data, const tflite::RuntimeShape &bias_shape,
- const float *bias_data, float *scratchpad_data, float *activation_state_data,
- const tflite::RuntimeShape &output_shape, float *output_data)
-{
- const int32_t rank = params.rank;
- const int32_t batch_size = input_shape.Dims(0);
- const int32_t input_size = input_shape.Dims(1);
- const int32_t num_filters = weight_feature_shape.Dims(0);
- const int32_t num_units = num_filters / rank;
- const int32_t memory_size = weight_time_shape.Dims(1);
-
- // Left shift the activation_state.
- {
- float *new_state_start = activation_state_data;
- const float *old_state_start = activation_state_data + 1;
- const float *old_state_end = activation_state_data + batch_size * num_filters * memory_size;
- while (old_state_start != old_state_end)
- {
- *new_state_start++ = *old_state_start++;
- }
- }
-
- // Note: no need to clear the latest activation, matmul is not accumulative.
-
- // Compute conv1d(inputs, weights_feature).
- // The activation_state's rightmost column is used to save current cycle
- // activation. This is achieved by starting at state_ptr[memory_size - 1] and
- // having the stride equal to memory_size.
-
- // Perform batched matrix vector multiply operation:
- {
- const float *matrix = weight_feature_data;
- const float *vector = input_data;
- float *result = &activation_state_data[memory_size - 1];
- float *result_in_batch = result;
- for (int i = 0; i < batch_size; ++i)
- {
- const float *matrix_ptr = matrix;
- for (int j = 0; j < num_filters; ++j)
- {
- float dot_prod = 0.0f;
- const float *vector_in_batch = vector + i * input_size;
- for (int k = 0; k < input_size; ++k)
- {
- dot_prod += *matrix_ptr++ * *vector_in_batch++;
- }
- *result_in_batch = dot_prod;
- result_in_batch += memory_size;
- }
- }
- }
-
- tflite::reference_ops::ApplyTimeWeightsBiasAndActivation(
- batch_size, memory_size, num_filters, num_units, rank, weight_time_data, bias_data,
- params.activation, activation_state_data, scratchpad_data, output_data);
-}
-
-static inline void SetupScratchpadTensor(
- const luci_interpreter::DataType &input_data_type,
- const luci_interpreter::DataType &weight_feature_data_type,
- luci_interpreter::Tensor *scratchpad_1, luci_interpreter::Tensor *scratchpad_2,
- luci_interpreter::Tensor *scratchpad_3, luci_interpreter::Tensor *scratchpad_4,
- luci_interpreter::Tensor *scratchpad_5, luci_interpreter::Tensor *scratchpad_6,
- const luci_interpreter::Shape input_shape, const luci_interpreter::Shape weight_time_shape,
- const int32_t batch_size, const int32_t num_filters, const int32_t num_units)
-{
- if (input_data_type == luci_interpreter::DataType::FLOAT32 &&
- (weight_feature_data_type == luci_interpreter::DataType::S8 ||
- weight_feature_data_type == luci_interpreter::DataType::U8))
- {
- (void)input_shape;
- (void)weight_time_shape;
- (void)scratchpad_3;
- (void)scratchpad_4;
- (void)scratchpad_5;
- (void)scratchpad_6;
-
- assert(false && "Hybrid type is not supported for cmsisnn");
- }
-
- // Resize scratchpad_1 tensor
- scratchpad_1->resize({batch_size, num_filters});
-
- if (input_data_type == luci_interpreter::DataType::S8)
- {
- // Resize scratchpad_2 for full_integer op
- scratchpad_2->resize({batch_size, num_units});
- }
-}
-
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_SVDF_H
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALSoftmax.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALSoftmax.h
deleted file mode 100644
index 1fb186248..000000000
--- a/onert-micro/luci-interpreter/pal/cmsisnn/PALSoftmax.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_SOFTMAX_H
-#define LUCI_INTERPRETER_PAL_SOFTMAX_H
-
-#include <tensorflow/lite/kernels/internal/reference/softmax.h>
-#include <arm_nnfunctions.h>
-
-namespace luci_interpreter_pal
-{
-static inline void PopulateSoftmaxLookupTable(tflite::SoftmaxParams *data, float input_scale,
- float beta)
-{
- // Do nothing for mcu
- (void)data;
- (void)input_scale;
- (void)beta;
-}
-
-static inline void InitializeParams(tflite::SoftmaxParams *params, float input_scale, float beta)
-{
- int32 input_beta_multiplier;
- int input_beta_left_shift;
- static const int kScaledDiffIntegerBits = 5;
- tflite::PreprocessSoftmaxScaling(beta, input_scale, kScaledDiffIntegerBits,
- &input_beta_multiplier, &input_beta_left_shift);
-
- params->input_multiplier = input_beta_multiplier;
- params->input_left_shift = input_beta_left_shift;
- params->diff_min =
- -tflite::CalculateInputRadius(kScaledDiffIntegerBits, params->input_left_shift);
-}
-
-template <typename T>
-static inline void Softmax(const tflite::SoftmaxParams &params,
- const tflite::RuntimeShape &input_shape, const T *input_data,
- const tflite::RuntimeShape &output_shape, T *output_data)
-{
- // MARK: At this moment this operation doesn't support on mcu
- assert(false && "Softmax NYI");
- (void)params;
- (void)input_shape;
- (void)input_data;
- (void)output_shape;
- (void)output_data;
-}
-
-template <>
-inline void Softmax<int8_t>(const tflite::SoftmaxParams &params,
- const tflite::RuntimeShape &input_shape, const int8_t *input_data,
- const tflite::RuntimeShape &output_shape, int8_t *output_data)
-{
- const int trailing_dim = input_shape.DimensionsCount() - 1;
- const int outer_size = tflite::MatchingFlatSizeSkipDim(input_shape, trailing_dim, output_shape);
- const int depth = tflite::MatchingDim(input_shape, trailing_dim, output_shape, trailing_dim);
- const int32_t mult = params.input_multiplier;
- const int32_t shift = params.input_left_shift;
- const int32_t diff_min = params.diff_min;
-
- arm_softmax_s8(input_data, outer_size, depth, mult, shift, diff_min, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_SOFTMAX_H
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALSpaceToBatchND.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALSpaceToBatchND.h
deleted file mode 100644
index 7997c710c..000000000
--- a/onert-micro/luci-interpreter/pal/cmsisnn/PALSpaceToBatchND.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_SPACETOBATCHND_H
-#define LUCI_INTERPRETER_PAL_SPACETOBATCHND_H
-
-#include <tensorflow/lite/kernels/internal/reference/space_to_batch_nd.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void
-SpaceToBatchND(const tflite::SpaceToBatchParams &params,
- const tflite::RuntimeShape &unextended_input1_shape, const T *input1_data,
- const tflite::RuntimeShape &unextended_input2_shape, const int32 *block_shape_data,
- const tflite::RuntimeShape &unextended_input3_shape, const int32 *paddings_data,
- const tflite::RuntimeShape &unextended_output_shape, T *output_data)
-{
- tflite::reference_ops::SpaceToBatchND(
- params, unextended_input1_shape, input1_data, unextended_input2_shape, block_shape_data,
- unextended_input3_shape, paddings_data, unextended_output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_SPACETOBATCHND_H
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALSpaceToDepth.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALSpaceToDepth.h
deleted file mode 100644
index 7866cc2c6..000000000
--- a/onert-micro/luci-interpreter/pal/cmsisnn/PALSpaceToDepth.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_SPACETODEPTH_H
-#define LUCI_INTERPRETER_PAL_SPACETODEPTH_H
-
-#include <tensorflow/lite/kernels/internal/reference/space_to_depth.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void SpaceToDepth(const tflite::SpaceToDepthParams &op_params,
- const tflite::RuntimeShape &unextended_input_shape,
- const T *input_data,
- const tflite::RuntimeShape &unextended_output_shape, T *output_data)
-{
- tflite::reference_ops::SpaceToDepth(op_params, unextended_input_shape, input_data,
- unextended_output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_SPACETODEPTH_H
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALSub.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALSub.h
index 2269bc3a6..ea57578c6 100644
--- a/onert-micro/luci-interpreter/pal/cmsisnn/PALSub.h
+++ b/onert-micro/luci-interpreter/pal/cmsisnn/PALSub.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALreference_ops.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALreference_ops.h
deleted file mode 100644
index 62c720937..000000000
--- a/onert-micro/luci-interpreter/pal/cmsisnn/PALreference_ops.h
+++ /dev/null
@@ -1,1556 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_REFERENCE_OPS_H
-#define LUCI_INTERPRETER_PAL_REFERENCE_OPS_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <algorithm>
-#include <cmath>
-#include <cstring>
-#include <functional>
-#include <limits>
-#include <memory>
-#include <type_traits>
-
-#include "third_party/eigen3/Eigen/Core"
-#include "fixedpoint/fixedpoint.h"
-#include "ruy/profiler/instrumentation.h" // from @ruy
-#include "tensorflow/lite/c/common.h"
-#include "tensorflow/lite/kernels/internal/common.h"
-#include "tensorflow/lite/kernels/internal/quantization_util.h"
-#include "tensorflow/lite/kernels/internal/reference/add.h"
-#include "tensorflow/lite/kernels/internal/reference/add_n.h"
-#include "tensorflow/lite/kernels/internal/reference/arg_min_max.h"
-#include "tensorflow/lite/kernels/internal/reference/batch_matmul.h"
-#include "tensorflow/lite/kernels/internal/reference/batch_to_space_nd.h"
-#include "tensorflow/lite/kernels/internal/reference/binary_function.h"
-#include "tensorflow/lite/kernels/internal/reference/cast.h"
-#include "tensorflow/lite/kernels/internal/reference/ceil.h"
-#include "tensorflow/lite/kernels/internal/reference/comparisons.h"
-#include "tensorflow/lite/kernels/internal/reference/concatenation.h"
-#include "tensorflow/lite/kernels/internal/reference/conv.h"
-#include "tensorflow/lite/kernels/internal/reference/depth_to_space.h"
-#include "tensorflow/lite/kernels/internal/reference/dequantize.h"
-#include "tensorflow/lite/kernels/internal/reference/div.h"
-#include "tensorflow/lite/kernels/internal/reference/elu.h"
-#include "tensorflow/lite/kernels/internal/reference/exp.h"
-#include "tensorflow/lite/kernels/internal/reference/fill.h"
-#include "tensorflow/lite/kernels/internal/reference/floor.h"
-#include "tensorflow/lite/kernels/internal/reference/floor_div.h"
-#include "tensorflow/lite/kernels/internal/reference/floor_mod.h"
-#include "tensorflow/lite/kernels/internal/reference/fully_connected.h"
-#include "tensorflow/lite/kernels/internal/reference/gather.h"
-#include "tensorflow/lite/kernels/internal/reference/hard_swish.h"
-#include "tensorflow/lite/kernels/internal/reference/l2normalization.h"
-#include "tensorflow/lite/kernels/internal/reference/leaky_relu.h"
-#include "tensorflow/lite/kernels/internal/reference/log_softmax.h"
-#include "tensorflow/lite/kernels/internal/reference/logistic.h"
-#include "tensorflow/lite/kernels/internal/reference/maximum_minimum.h"
-#include "tensorflow/lite/kernels/internal/reference/mul.h"
-#include "tensorflow/lite/kernels/internal/reference/neg.h"
-#include "tensorflow/lite/kernels/internal/reference/pad.h"
-#include "tensorflow/lite/kernels/internal/reference/pooling.h"
-#include "tensorflow/lite/kernels/internal/reference/prelu.h"
-#include "tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h"
-#include "tensorflow/lite/kernels/internal/reference/quantize.h"
-#include "tensorflow/lite/kernels/internal/reference/reduce.h"
-#include "tensorflow/lite/kernels/internal/reference/requantize.h"
-#include "tensorflow/lite/kernels/internal/reference/resize_bilinear.h"
-#include "tensorflow/lite/kernels/internal/reference/resize_nearest_neighbor.h"
-#include "tensorflow/lite/kernels/internal/reference/round.h"
-#include "tensorflow/lite/kernels/internal/reference/softmax.h"
-#include "tensorflow/lite/kernels/internal/reference/space_to_batch_nd.h"
-#include "tensorflow/lite/kernels/internal/reference/space_to_depth.h"
-#include "tensorflow/lite/kernels/internal/reference/strided_slice.h"
-#include "tensorflow/lite/kernels/internal/reference/string_comparisons.h"
-#include "tensorflow/lite/kernels/internal/reference/sub.h"
-#include "tensorflow/lite/kernels/internal/reference/tanh.h"
-#include "tensorflow/lite/kernels/internal/reference/transpose.h"
-#include "tensorflow/lite/kernels/internal/reference/transpose_conv.h"
-#include "tensorflow/lite/kernels/internal/strided_slice_logic.h"
-#include "tensorflow/lite/kernels/internal/tensor.h"
-#include "tensorflow/lite/kernels/internal/types.h"
-namespace tflite
-{
-
-namespace reference_ops
-{
-
-template <typename T>
-inline void Relu(const RuntimeShape &input_shape, const T *input_data,
- const RuntimeShape &output_shape, T *output_data)
-{
- const int flat_size = MatchingFlatSize(input_shape, output_shape);
- for (int i = 0; i < flat_size; ++i)
- {
- const T val = input_data[i];
- const T lower = 0;
- const T clamped = val < lower ? lower : val;
- output_data[i] = clamped;
- }
-}
-
-template <typename T>
-inline void Relu1(const RuntimeShape &input_shape, const T *input_data,
- const RuntimeShape &output_shape, T *output_data)
-{
- ruy::profiler::ScopeLabel label("Relu1 (not fused)");
- const int flat_size = MatchingFlatSize(input_shape, output_shape);
- for (int i = 0; i < flat_size; ++i)
- {
- const T val = input_data[i];
- const T upper = 1;
- const T lower = -1;
- const T clamped = val > upper ? upper : val < lower ? lower : val;
- output_data[i] = clamped;
- }
-}
-
-inline void Relu6(const RuntimeShape &input_shape, const float *input_data,
- const RuntimeShape &output_shape, float *output_data)
-{
- ruy::profiler::ScopeLabel label("Relu6 (not fused)");
- const int flat_size = MatchingFlatSize(input_shape, output_shape);
- for (int i = 0; i < flat_size; ++i)
- {
- const float val = input_data[i];
- const float upper = 6;
- const float lower = 0;
- const float clamped = val > upper ? upper : val < lower ? lower : val;
- output_data[i] = clamped;
- }
-}
-
-template <typename T>
-inline void ReluX(const tflite::ReluParams &params, const RuntimeShape &input_shape,
- const T *input_data, const RuntimeShape &output_shape, T *output_data)
-{
- ruy::profiler::ScopeLabel label("Quantized ReluX (not fused)");
- const int flat_size = MatchingFlatSize(input_shape, output_shape);
- for (int i = 0; i < flat_size; ++i)
- {
- const int32 val = static_cast<int32_t>(input_data[i]);
- int32 clamped = params.output_offset + MultiplyByQuantizedMultiplier(val - params.input_offset,
- params.output_multiplier,
- params.output_shift);
- clamped = std::max(params.quantized_activation_min, clamped);
- clamped = std::min(params.quantized_activation_max, clamped);
- output_data[i] = static_cast<T>(clamped);
- }
-}
-
-template <typename T>
-inline void ReluX(const tflite::ActivationParams &params, const RuntimeShape &input_shape,
- const T *input_data, const RuntimeShape &output_shape, T *output_data)
-{
- ruy::profiler::ScopeLabel label("Quantized ReluX (not fused)");
- const int flat_size = MatchingFlatSize(input_shape, output_shape);
- const T max_value = params.quantized_activation_max;
- const T min_value = params.quantized_activation_min;
- for (int i = 0; i < flat_size; ++i)
- {
- const T val = input_data[i];
- const T clamped = val > max_value ? max_value : val < min_value ? min_value : val;
- output_data[i] = clamped;
- }
-}
-
-// TODO(jiawen): We can implement BroadcastMul on buffers of arbitrary
-// dimensionality if the runtime code does a single loop over one dimension
-// that handles broadcasting as the base case. The code generator would then
-// generate max(D1, D2) nested for loops.
-inline void BroadcastMulFivefold(const ArithmeticParams &unswitched_params,
- const RuntimeShape &unswitched_input1_shape,
- const uint8 *unswitched_input1_data,
- const RuntimeShape &unswitched_input2_shape,
- const uint8 *unswitched_input2_data,
- const RuntimeShape &output_shape, uint8 *output_data)
-{
- ArithmeticParams switched_params = unswitched_params;
- switched_params.input1_offset = unswitched_params.input2_offset;
- switched_params.input2_offset = unswitched_params.input1_offset;
-
- const bool use_unswitched = unswitched_params.broadcast_category ==
- tflite::BroadcastableOpCategory::kFirstInputBroadcastsFast;
-
- const ArithmeticParams &params = use_unswitched ? unswitched_params : switched_params;
- const uint8 *input1_data = use_unswitched ? unswitched_input1_data : unswitched_input2_data;
- const uint8 *input2_data = use_unswitched ? unswitched_input2_data : unswitched_input1_data;
-
- // Fivefold nested loops. The second input resets its position for each
- // iteration of the second loop. The first input resets its position at the
- // beginning of the fourth loop. The innermost loop is an elementwise Mul of
- // sections of the arrays.
- uint8 *output_data_ptr = output_data;
- const uint8 *input1_data_ptr = input1_data;
- const uint8 *input2_data_reset = input2_data;
- int y0 = params.broadcast_shape[0];
- int y1 = params.broadcast_shape[1];
- int y2 = params.broadcast_shape[2];
- int y3 = params.broadcast_shape[3];
- int y4 = params.broadcast_shape[4];
- for (int i0 = 0; i0 < y0; ++i0)
- {
- const uint8 *input2_data_ptr;
- for (int i1 = 0; i1 < y1; ++i1)
- {
- input2_data_ptr = input2_data_reset;
- for (int i2 = 0; i2 < y2; ++i2)
- {
- for (int i3 = 0; i3 < y3; ++i3)
- {
- MulElementwise(y4, params, input1_data_ptr, input2_data_ptr, output_data_ptr);
- input2_data_ptr += y4;
- output_data_ptr += y4;
- }
- input1_data_ptr += y4;
- }
- }
- input2_data_reset = input2_data_ptr;
- }
-}
-
-inline void Mul(const ArithmeticParams &params, const RuntimeShape &input1_shape,
- const int16 *input1_data, const RuntimeShape &input2_shape,
- const int16 *input2_data, const RuntimeShape &output_shape, int16 *output_data)
-{
- ruy::profiler::ScopeLabel label("Mul/Int16");
-
- const int flat_size = MatchingElementsSize(input1_shape, input2_shape, output_shape);
-
- for (int i = 0; i < flat_size; i++)
- {
- // F0 uses 0 integer bits, range [-1, 1].
- using F0 = gemmlowp::FixedPoint<std::int16_t, 0>;
-
- F0 unclamped_result = F0::FromRaw(input1_data[i]) * F0::FromRaw(input2_data[i]);
- output_data[i] = unclamped_result.raw();
- }
-}
-
-inline void Mul(const ArithmeticParams &params, const RuntimeShape &input1_shape,
- const int16 *input1_data, const RuntimeShape &input2_shape,
- const int16 *input2_data, const RuntimeShape &output_shape, uint8 *output_data)
-{
- ruy::profiler::ScopeLabel label("Mul/Int16Uint8");
- int32 output_offset = params.output_offset;
- int32 output_activation_min = params.quantized_activation_min;
- int32 output_activation_max = params.quantized_activation_max;
- TFLITE_DCHECK_LE(output_activation_min, output_activation_max);
-
- const int flat_size = MatchingElementsSize(input1_shape, input2_shape, output_shape);
-
- for (int i = 0; i < flat_size; i++)
- {
- // F0 uses 0 integer bits, range [-1, 1].
- using F0 = gemmlowp::FixedPoint<std::int16_t, 0>;
-
- F0 unclamped_result = F0::FromRaw(input1_data[i]) * F0::FromRaw(input2_data[i]);
- int16 rescaled_result = gemmlowp::RoundingDivideByPOT(unclamped_result.raw(), 8);
- int16 clamped_result = std::min<int16>(output_activation_max - output_offset, rescaled_result);
- clamped_result = std::max<int16>(output_activation_min - output_offset, clamped_result);
- output_data[i] = output_offset + clamped_result;
- }
-}
-
-inline void Sub16(const ArithmeticParams &params, const RuntimeShape &input1_shape,
- const int16_t *input1_data, const RuntimeShape &input2_shape,
- const int16_t *input2_data, const RuntimeShape &output_shape,
- int16_t *output_data)
-{
- ruy::profiler::ScopeLabel label("Sub/Int16");
- const int input1_shift = params.input1_shift;
- const int flat_size = MatchingElementsSize(input1_shape, input2_shape, output_shape);
- const int16 output_activation_min = params.quantized_activation_min;
- const int16 output_activation_max = params.quantized_activation_max;
-
- TFLITE_DCHECK(input1_shift == 0 || params.input2_shift == 0);
- TFLITE_DCHECK_LE(input1_shift, 0);
- TFLITE_DCHECK_LE(params.input2_shift, 0);
- const int16 *not_shift_input = input1_shift == 0 ? input1_data : input2_data;
- const int16 *shift_input = input1_shift == 0 ? input2_data : input1_data;
- const int input_right_shift = input1_shift == 0 ? -params.input2_shift : -input1_shift;
-
- if (input1_shift == 0)
- {
- // F0 uses 0 integer bits, range [-1, 1].
- using F0 = gemmlowp::FixedPoint<std::int16_t, 0>;
- for (int i = 0; i < flat_size; ++i)
- {
- F0 input_ready_scaled = F0::FromRaw(not_shift_input[i]);
- F0 scaled_input =
- F0::FromRaw(gemmlowp::RoundingDivideByPOT(shift_input[i], input_right_shift));
- F0 result = SaturatingSub(input_ready_scaled, scaled_input);
- const int16 raw_output = result.raw();
- const int16 clamped_output =
- std::min(output_activation_max, std::max(output_activation_min, raw_output));
- output_data[i] = clamped_output;
- }
- }
- else
- {
- // F0 uses 0 integer bits, range [-1, 1].
- using F0 = gemmlowp::FixedPoint<std::int16_t, 0>;
- for (int i = 0; i < flat_size; ++i)
- {
- F0 input_ready_scaled = F0::FromRaw(not_shift_input[i]);
- F0 scaled_input =
- F0::FromRaw(gemmlowp::RoundingDivideByPOT(shift_input[i], input_right_shift));
- F0 result = SaturatingSub(scaled_input, input_ready_scaled);
- const int16 raw_output = result.raw();
- const int16 clamped_output =
- std::min(output_activation_max, std::max(output_activation_min, raw_output));
- output_data[i] = clamped_output;
- }
- }
-}
-
-template <typename Scalar>
-void Pack(const PackParams &params, const RuntimeShape *const *input_shapes,
- const Scalar *const *input_data, const RuntimeShape &output_shape, Scalar *output_data)
-{
- ruy::profiler::ScopeLabel label("Pack");
- const int dimensions = output_shape.DimensionsCount();
- int axis = params.axis;
- int inputs_count = params.inputs_count;
-
- int outer_size = 1;
- for (int i = 0; i < axis; i++)
- {
- outer_size *= output_shape.Dims(i);
- }
- int copy_size = 1;
- for (int i = params.axis + 1; i < dimensions; i++)
- {
- copy_size *= output_shape.Dims(i);
- }
- TFLITE_DCHECK_EQ((**input_shapes).FlatSize(), copy_size * outer_size);
-
- for (int i = 0; i < inputs_count; ++i)
- {
- for (int k = 0; k < outer_size; k++)
- {
- const Scalar *input_ptr = input_data[i] + copy_size * k;
- int loc = k * inputs_count * copy_size + i * copy_size;
- memcpy(output_data + loc, input_ptr, copy_size * sizeof(Scalar));
- }
- }
-}
-
-template <typename Scalar>
-void Unpack(const UnpackParams &params, const RuntimeShape &input_shape, const Scalar *input_data,
- const RuntimeShape &output_shape, Scalar *const *output_datas)
-{
- ruy::profiler::ScopeLabel label("Unpack");
- const int dimensions = input_shape.DimensionsCount();
- const int outputs_count = params.num_split;
-
- int outer_size = 1;
- int axis = params.axis;
- if (axis < 0)
- {
- axis += dimensions;
- }
- TFLITE_DCHECK_GE(axis, 0);
- TFLITE_DCHECK_LT(axis, dimensions);
- for (int i = 0; i < axis; ++i)
- {
- outer_size *= input_shape.Dims(i);
- }
- int copy_size = 1;
- for (int i = axis + 1; i < dimensions; ++i)
- {
- copy_size *= input_shape.Dims(i);
- }
- TFLITE_DCHECK_EQ(output_shape.FlatSize(), copy_size * outer_size);
-
- for (int i = 0; i < outputs_count; ++i)
- {
- for (int k = 0; k < outer_size; k++)
- {
- Scalar *output_ptr = output_datas[i] + copy_size * k;
- int loc = k * outputs_count * copy_size + i * copy_size;
- memcpy(output_ptr, input_data + loc, copy_size * sizeof(Scalar));
- }
- }
-}
-
-template <typename Scalar>
-void PackWithScaling(const PackParams &params, const RuntimeShape *const *input_shapes,
- const uint8 *const *input_data, const RuntimeShape &output_shape,
- uint8 *output_data)
-{
- ruy::profiler::ScopeLabel label("PackWithScaling");
- const int dimensions = output_shape.DimensionsCount();
- int axis = params.axis;
- const int32 *input_zeropoint = params.input_zeropoint;
- const float *input_scale = params.input_scale;
- int inputs_count = params.inputs_count;
- const int32 output_zeropoint = params.output_zeropoint;
- const float output_scale = params.output_scale;
-
- int outer_size = 1;
- for (int i = 0; i < axis; i++)
- {
- outer_size *= output_shape.Dims(i);
- }
- int copy_size = 1;
- for (int i = axis + 1; i < dimensions; i++)
- {
- copy_size *= output_shape.Dims(i);
- }
- TFLITE_DCHECK_EQ((**input_shapes).FlatSize(), copy_size * outer_size);
-
- Scalar *output_ptr = output_data;
- const float inverse_output_scale = 1.f / output_scale;
- for (int k = 0; k < outer_size; k++)
- {
- for (int i = 0; i < inputs_count; ++i)
- {
- if (input_zeropoint[i] == output_zeropoint && input_scale[i] == output_scale)
- {
- memcpy(output_ptr, input_data[i] + k * copy_size, copy_size * sizeof(Scalar));
- }
- else
- {
- assert(false);
- const float scale = input_scale[i] * inverse_output_scale;
- const float bias = -input_zeropoint[i] * scale;
- auto input_ptr = input_data[i];
- for (int j = 0; j < copy_size; ++j)
- {
- const int value =
- static_cast<int32_t>(std::round(input_ptr[j] * scale + bias)) + output_zeropoint;
- output_ptr[j] = static_cast<uint8_t>(std::max(std::min(255, value), 0));
- }
- }
- output_ptr += copy_size;
- }
- }
-}
-
-template <typename Scalar>
-void DepthConcatenation(const ConcatenationParams &params, const RuntimeShape *const *input_shapes,
- const Scalar *const *input_data, const RuntimeShape &output_shape,
- Scalar *output_data)
-{
- ruy::profiler::ScopeLabel label("DepthConcatenation");
- auto params_copy = params;
- params_copy.axis = 3;
- Concatenation(params_copy, input_shapes, input_data, output_shape, output_data);
-}
-
-inline void LstmCell(const LstmCellParams &params, const RuntimeShape &unextended_input_shape,
- const float *input_data, const RuntimeShape &unextended_prev_activ_shape,
- const float *prev_activ_data, const RuntimeShape &weights_shape,
- const float *weights_data, const RuntimeShape &unextended_bias_shape,
- const float *bias_data, const RuntimeShape &unextended_prev_state_shape,
- const float *prev_state_data,
- const RuntimeShape &unextended_output_state_shape, float *output_state_data,
- const RuntimeShape &unextended_output_activ_shape, float *output_activ_data,
- const RuntimeShape &unextended_concat_temp_shape, float *concat_temp_data,
- const RuntimeShape &unextended_activ_temp_shape, float *activ_temp_data)
-{
- TFLITE_DCHECK_LE(unextended_input_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_prev_activ_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_bias_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_prev_state_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_output_state_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_output_activ_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_concat_temp_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_activ_temp_shape.DimensionsCount(), 4);
- const RuntimeShape input_shape = RuntimeShape::ExtendedShape(4, unextended_input_shape);
- const RuntimeShape prev_activ_shape = RuntimeShape::ExtendedShape(4, unextended_prev_activ_shape);
- const RuntimeShape bias_shape = RuntimeShape::ExtendedShape(4, unextended_bias_shape);
- const RuntimeShape prev_state_shape = RuntimeShape::ExtendedShape(4, unextended_prev_state_shape);
- const RuntimeShape output_state_shape =
- RuntimeShape::ExtendedShape(4, unextended_output_state_shape);
- const RuntimeShape output_activ_shape =
- RuntimeShape::ExtendedShape(4, unextended_output_activ_shape);
- const RuntimeShape concat_temp_shape =
- RuntimeShape::ExtendedShape(4, unextended_concat_temp_shape);
- const RuntimeShape activ_temp_shape = RuntimeShape::ExtendedShape(4, unextended_activ_temp_shape);
- TFLITE_DCHECK_GE(weights_shape.DimensionsCount(), 2);
-
- const int weights_dim_count = weights_shape.DimensionsCount();
- const int batches = MatchingDim(input_shape, 0, prev_activ_shape, 0, prev_state_shape, 0,
- output_state_shape, 0, output_activ_shape, 0);
- const int height = MatchingDim(input_shape, 1, prev_activ_shape, 1, prev_state_shape, 1,
- output_state_shape, 1, output_activ_shape, 1);
- const int width = MatchingDim(input_shape, 2, prev_activ_shape, 2, prev_state_shape, 2,
- output_state_shape, 2, output_activ_shape, 2);
- const int input_depth = input_shape.Dims(3);
- const int prev_activ_depth = prev_activ_shape.Dims(3);
- const int total_input_depth = prev_activ_depth + input_depth;
- TFLITE_DCHECK_EQ(weights_shape.Dims(weights_dim_count - 1), total_input_depth);
- TFLITE_DCHECK_EQ(FlatSizeSkipDim(bias_shape, 3), 1);
- const int intern_activ_depth = MatchingDim(weights_shape, weights_dim_count - 2, bias_shape, 3);
- TFLITE_DCHECK_EQ(weights_shape.FlatSize(), intern_activ_depth * total_input_depth);
- TFLITE_DCHECK_EQ(intern_activ_depth % 4, 0);
- const int output_depth = MatchingDim(prev_state_shape, 3, prev_activ_shape, 3, output_state_shape,
- 3, output_activ_shape, 3);
- TFLITE_DCHECK_EQ(output_depth, intern_activ_depth / 4);
-
- // Concatenate prev_activ and input data together
- std::vector<float const *> concat_input_arrays_data;
- std::vector<RuntimeShape const *> concat_input_arrays_shapes;
- concat_input_arrays_data.push_back(input_data);
- concat_input_arrays_data.push_back(prev_activ_data);
- concat_input_arrays_shapes.push_back(&input_shape);
- concat_input_arrays_shapes.push_back(&prev_activ_shape);
- tflite::ConcatenationParams concat_params;
- concat_params.axis = 3;
- concat_params.inputs_count = concat_input_arrays_data.size();
- Concatenation(concat_params, &(concat_input_arrays_shapes[0]), &(concat_input_arrays_data[0]),
- concat_temp_shape, concat_temp_data);
-
- // Fully connected
- tflite::FullyConnectedParams fc_params;
- fc_params.float_activation_min = std::numeric_limits<float>::lowest();
- fc_params.float_activation_max = std::numeric_limits<float>::max();
- FullyConnected(fc_params, concat_temp_shape, concat_temp_data, weights_shape, weights_data,
- bias_shape, bias_data, activ_temp_shape, activ_temp_data);
-
- // Memory state update (the LSTM "guts")
- for (int b = 0; b < batches; ++b)
- {
- for (int w = 0; w < width; ++w)
- {
- for (int h = 0; h < height; ++h)
- {
- for (int c = 0; c < output_depth; ++c)
- {
- const float input_gate =
- 1.f /
- (1.f +
- std::exp(-activ_temp_data[Offset(activ_temp_shape, b, h, w, 0 * output_depth + c)]));
- const float new_input =
- std::tanh(activ_temp_data[Offset(activ_temp_shape, b, h, w, 1 * output_depth + c)]);
- const float forget_gate =
- 1.f /
- (1.f +
- std::exp(-activ_temp_data[Offset(activ_temp_shape, b, h, w, 2 * output_depth + c)]));
- const float output_gate =
- 1.f /
- (1.f +
- std::exp(-activ_temp_data[Offset(activ_temp_shape, b, h, w, 3 * output_depth + c)]));
- const float new_state =
- input_gate * new_input +
- forget_gate * prev_state_data[Offset(prev_state_shape, b, h, w, c)];
- output_state_data[Offset(output_state_shape, b, h, w, c)] = new_state;
- output_activ_data[Offset(output_activ_shape, b, h, w, c)] =
- output_gate * std::tanh(new_state);
- }
- }
- }
- }
-}
-
-// Quantized LSTM cell implementation.
-// The quantization of the input, output arrays is as follows:
-// - The input activations are quantized as uint8 on the interval
-// [-1, 127/128].
-// The rationale for that is that is the natural interval for output
-// activations (see next point) and these need to be concatenated together.
-// We could accommodate different ranges by re-scaling, but we empirically
-// found that setting the input activations range to be [-1, 127/128] in the
-// first place, removing the need for re-scaling, greatly improves accuracy.
-// - The output activations are quantized as uint8 on the interval
-// [-1, 127/128].
-// The rationale for that is that the definition of a LSTM cell makes them
-// intrinsically constrained in [-1, 1]; tweaking that to [-1, 127/128]
-// makes for simpler, more accurate fixed-point arithmetic.
-// - The output-at-previous-timestep state array is obviously quantized as
-// the output activations.
-// - The internal LSTM memory (not the output-at-previous-timestep, the other
-// internal state array) is int16-quantized and may use any power-of-two,
-// symmetric range i.e. [-2^N, 2^N * 32767/32768] for any N, which we call
-// StateIntegerBits below, see the below discussion of that template
-// parameter ("The StateIntegerBits template parameter").
-// - The output of the internal fully-connected node is int16-quantized
-// on the interval [-8, 8 * 32767/32768], the rationale for which is
-// explained just below ("Why [-8, 8] for fully-connected output?").
-//
-//
-// === The StateIntegerBits template parameter ===
-//
-// The StateIntegerBits template parameter controls the fixed-point format used
-// to represent the internal memory of the LSTM cell (not the
-// output-at-previous-timestep, the other internal state array). It's currently
-// a template parameter so that the model can control that. The most typical
-// value for StateIntegerBits is 4. Other plausible values are anywhere between
-// 3 and 5. We might eventually standardize on a single supported value, e.g. 4,
-// and drop that template parameter. The reason why it can't be a runtime
-// parameter is that this controls the fixed-point format used, i.e. we need to
-// generate actually different code based on it. In particular, we generate code
-// for a fixed-point tanh() implementation for that format, which internally
-// uses a fixed-point exp() implementation, which internally uses a
-// barrel-shifter with a number of steps that depends on StateIntegerBits.
-// Another consequence of that is that a higher value of StateIntegerBits
-// results in a more expensive implementation (more barrel shifter steps
-// needed).
-//
-//
-// === Why [-8, 8] for fully-connected output? ===
-//
-// This array is only fed to Logistic and Tanh functions, for which
-// the quantized implementation will want to use fixed-point arithmetic,
-// requiring a power-of-two representation interval. Thus, we should right
-// away quantize this array to a power-of-two interval; otherwise,
-// implementation will need to rescale that, losing any benefit that a tighter
-// representation interval might otherwise yield, while introducing some
-// numerical error and computational overhead.
-//
-// Now, Logistic and Tanh
-// are nearly constant (nearly equal to their horizontal asymptotes)
-// outside of a small bounded interval around 0:
-//
-// Logistic(4) = 1 - 1.8e-2 Tanh(4) = 1 - 6.7e-4
-// Logistic(8) = 1 - 3.4e-4 Tanh(8) = 1 - 2.3e-7
-// Logistic(16) = 1 - 1.1e-7 Tanh(16) = 1 - 2.5e-14
-//
-// From this, we see that clamping to [-4, 4] would be too inaccurate
-// (the error of 1.8e-2 on Logistic would be felt even in 8bit precision)
-// while clamping to [-16, 16] would make no difference even in float32.
-// However, for a fixed-point implementation in 16-bit integers, using 5
-// integer bits to represent the [-16, 16] range would leave only 11
-// fractional bits, giving an increment of 2^-11 = 4.9e-4 between consecutive
-// representable values. Notice that is higher than the
-// worst-case clamping error with clamping to [-8, 8]: 3.4e-4 for Logistic.
-// Using [-8, 8] thus seems like the better compromise overall, enjoying
-// an increment of 2.4e-4 between representable values and a worst-case
-// clamping error of 3.4e-4, both better than the increment of 4.9e-4 with
-// [-16, 16].
-//
-// Moreover, all other things being equal, it is nice to choose the narrower
-// representation range, as that makes the implementation of fixed-point
-// math functions a little cheaper (each integer bit requires an additional
-// barrel-shifter atep in the implementation of exp(-x)). That is further
-// reason to prefer [-8, 8] over [-16, 16]. The choice of [-16, 16] would make
-// sense for 32-bit float or 32-bit fixed-point quantization, but we are
-// aiming for 16-bit fixed-point quantization of these internal nodes here.
-//
-template <int StateIntegerBits>
-inline void
-LstmCell(const LstmCellParams &params, const RuntimeShape &unextended_input_shape,
- const uint8 *input_data_uint8, const RuntimeShape &unextended_prev_activ_shape,
- const uint8 *prev_activ_data_uint8, const RuntimeShape &weights_shape,
- const uint8 *weights_data_uint8, const RuntimeShape &unextended_bias_shape,
- const int32 *bias_data_int32, const RuntimeShape &unextended_prev_state_shape,
- const int16 *prev_state_data_int16, const RuntimeShape &unextended_output_state_shape,
- int16 *output_state_data_int16, const RuntimeShape &unextended_output_activ_shape,
- uint8 *output_activ_data_uint8, const RuntimeShape &unextended_concat_temp_shape,
- uint8 *concat_temp_data_uint8, const RuntimeShape &unextended_activ_temp_shape,
- int16 *activ_temp_data_int16, void *gemmlowp_context)
-{
- (void)gemmlowp_context; // only used in optimized code.
- int32 weights_zero_point = params.weights_zero_point;
- int32 accum_multiplier = params.accum_multiplier;
- int accum_shift = params.accum_shift;
- TFLITE_DCHECK_LE(unextended_input_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_prev_activ_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_bias_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_prev_state_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_output_state_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_output_activ_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_concat_temp_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_activ_temp_shape.DimensionsCount(), 4);
- const RuntimeShape input_shape = RuntimeShape::ExtendedShape(4, unextended_input_shape);
- const RuntimeShape prev_activ_shape = RuntimeShape::ExtendedShape(4, unextended_prev_activ_shape);
- const RuntimeShape bias_shape = RuntimeShape::ExtendedShape(4, unextended_bias_shape);
- const RuntimeShape prev_state_shape = RuntimeShape::ExtendedShape(4, unextended_prev_state_shape);
- const RuntimeShape output_state_shape =
- RuntimeShape::ExtendedShape(4, unextended_output_state_shape);
- const RuntimeShape output_activ_shape =
- RuntimeShape::ExtendedShape(4, unextended_output_activ_shape);
- const RuntimeShape concat_temp_shape =
- RuntimeShape::ExtendedShape(4, unextended_concat_temp_shape);
- const RuntimeShape activ_temp_shape = RuntimeShape::ExtendedShape(4, unextended_activ_temp_shape);
- TFLITE_DCHECK_GE(weights_shape.DimensionsCount(), 2);
-
- // Gather dimensions information, and perform consistency checks.
- const int weights_dim_count = weights_shape.DimensionsCount();
- const int outer_size = MatchingFlatSizeSkipDim(input_shape, 3, prev_activ_shape, prev_state_shape,
- output_state_shape, output_activ_shape);
- const int input_depth = input_shape.Dims(3);
- const int prev_activ_depth = prev_activ_shape.Dims(3);
- const int total_input_depth = prev_activ_depth + input_depth;
- TFLITE_DCHECK_EQ(weights_shape.Dims(weights_dim_count - 1), total_input_depth);
- const int intern_activ_depth = MatchingDim(weights_shape, weights_dim_count - 2, bias_shape, 3);
- TFLITE_DCHECK_EQ(weights_shape.FlatSize(), intern_activ_depth * total_input_depth);
- TFLITE_DCHECK_EQ(FlatSizeSkipDim(bias_shape, 3), 1);
- TFLITE_DCHECK_EQ(intern_activ_depth % 4, 0);
- const int output_depth = MatchingDim(prev_state_shape, 3, prev_activ_shape, 3, output_state_shape,
- 3, output_activ_shape, 3);
- TFLITE_DCHECK_EQ(output_depth, intern_activ_depth / 4);
- const int fc_batches = FlatSizeSkipDim(activ_temp_shape, 3);
- const int fc_output_depth =
- MatchingDim(weights_shape, weights_dim_count - 2, activ_temp_shape, 3);
- const int fc_accum_depth = total_input_depth;
- TFLITE_DCHECK_EQ(fc_output_depth, 4 * output_depth);
-
- // Depth-concatenate prev_activ and input data together.
- uint8 const *concat_input_arrays_data[2] = {input_data_uint8, prev_activ_data_uint8};
- const RuntimeShape *concat_input_arrays_shapes[2] = {&input_shape, &prev_activ_shape};
- tflite::ConcatenationParams concat_params;
- concat_params.axis = 3;
- concat_params.inputs_count = 2;
- Concatenation(concat_params, concat_input_arrays_shapes, concat_input_arrays_data,
- concat_temp_shape, concat_temp_data_uint8);
-
- // Implementation of the fully connected node inside the LSTM cell.
- // The operands are 8-bit integers, the accumulators are internally 32bit
- // integers, and the output is 16-bit fixed-point with 3 integer bits so
- // the output range is [-2^3, 2^3] == [-8, 8]. The rationale for that
- // is explained in the function comment above.
- for (int b = 0; b < fc_batches; ++b)
- {
- for (int out_c = 0; out_c < fc_output_depth; ++out_c)
- {
- // Internal accumulation.
- // Initialize accumulator with the bias-value.
- int32 accum = bias_data_int32[out_c];
- // Accumulation loop.
- for (int d = 0; d < fc_accum_depth; ++d)
- {
- int16 input_val = concat_temp_data_uint8[b * fc_accum_depth + d] - 128;
- int16 weights_val = weights_data_uint8[out_c * fc_accum_depth + d] - weights_zero_point;
- accum += input_val * weights_val;
- }
- // Down-scale the final int32 accumulator to the scale used by our
- // (16-bit, using 3 integer bits) fixed-point format. The quantized
- // multiplier and shift here have been pre-computed offline
- // (e.g. by toco).
- accum = MultiplyByQuantizedMultiplier(accum, accum_multiplier, accum_shift);
- // Saturate, cast to int16, and store to the temporary activations array.
- accum = std::max(-32768, std::min(32767, static_cast<int>(accum)));
- activ_temp_data_int16[out_c + fc_output_depth * b] = accum;
- }
- }
-
- // Rest of the LSTM cell: tanh and logistic math functions, and some adds
- // and muls, all done in 16-bit fixed-point.
- for (int b = 0; b < outer_size; ++b)
- {
- for (int c = 0; c < output_depth; ++c)
- {
- // Define the fixed-point data types that we will use here. All use
- // int16 as the underlying integer type i.e. all are 16-bit fixed-point.
- // They only differ by the number of integral vs. fractional bits,
- // determining the range of values that they can represent.
- //
- // F0 uses 0 integer bits, range [-1, 1].
- // This is the return type of math functions such as tanh, logistic,
- // whose range is in [-1, 1].
- using F0 = gemmlowp::FixedPoint<std::int16_t, 0>;
- // F3 uses 3 integer bits, range [-8, 8].
- // This is the range of the previous fully-connected node's output,
- // which is our input here.
- using F3 = gemmlowp::FixedPoint<std::int16_t, 3>;
- // FS uses StateIntegerBits integer bits, range [-2^StateIntegerBits,
- // 2^StateIntegerBits]. It's used to represent the internal state, whose
- // number of integer bits is currently dictated by the model. See comment
- // on the StateIntegerBits template parameter above.
- using FS = gemmlowp::FixedPoint<std::int16_t, StateIntegerBits>;
- // Implementation of input gate, using fixed-point logistic function.
- F3 input_gate_input =
- F3::FromRaw(activ_temp_data_int16[b * fc_output_depth + 0 * output_depth + c]);
- F0 input_gate_output = gemmlowp::logistic(input_gate_input);
- // Implementation of input modulation gate, using fixed-point tanh
- // function.
- F3 input_modulation_gate_input =
- F3::FromRaw(activ_temp_data_int16[b * fc_output_depth + 1 * output_depth + c]);
- F0 input_modulation_gate_output = gemmlowp::tanh(input_modulation_gate_input);
- // Implementation of forget gate, using fixed-point logistic function.
- F3 forget_gate_input =
- F3::FromRaw(activ_temp_data_int16[b * fc_output_depth + 2 * output_depth + c]);
- F0 forget_gate_output = gemmlowp::logistic(forget_gate_input);
- // Implementation of output gate, using fixed-point logistic function.
- F3 output_gate_input =
- F3::FromRaw(activ_temp_data_int16[b * fc_output_depth + 3 * output_depth + c]);
- F0 output_gate_output = gemmlowp::logistic(output_gate_input);
- // Implementation of internal multiplication nodes, still in fixed-point.
- F0 input_times_input_modulation = input_gate_output * input_modulation_gate_output;
- FS prev_state = FS::FromRaw(prev_state_data_int16[b * output_depth + c]);
- FS prev_state_times_forget_state = forget_gate_output * prev_state;
- // Implementation of internal addition node, saturating.
- FS new_state =
- gemmlowp::SaturatingAdd(gemmlowp::Rescale<StateIntegerBits>(input_times_input_modulation),
- prev_state_times_forget_state);
- // Implementation of last internal Tanh node, still in fixed-point.
- // Since a Tanh fixed-point implementation is specialized for a given
- // number or integer bits, and each specialization can have a substantial
- // code size, and we already used above a Tanh on an input with 3 integer
- // bits, and per the table in the above function comment there is no
- // significant accuracy to be lost by clamping to [-8, +8] for a
- // 3-integer-bits representation, let us just do that. This helps people
- // porting this to targets where code footprint must be minimized.
- F3 new_state_f3 = gemmlowp::Rescale<3>(new_state);
- F0 output_activ_int16 = output_gate_output * gemmlowp::tanh(new_state_f3);
- // Store the new internal state back to memory, as 16-bit integers.
- // Note: here we store the original value with StateIntegerBits, not
- // the rescaled 3-integer-bits value fed to tanh.
- output_state_data_int16[b * output_depth + c] = new_state.raw();
- // Down-scale the output activations to 8-bit integers, saturating,
- // and store back to memory.
- int16 rescaled_output_activ = gemmlowp::RoundingDivideByPOT(output_activ_int16.raw(), 8);
- int16 clamped_output_activ =
- std::max<int16>(-128, std::min<int16>(127, rescaled_output_activ));
- output_activ_data_uint8[b * output_depth + c] = 128 + clamped_output_activ;
- }
- }
-}
-
-template <typename Scalar>
-void Split(const SplitParams &params, const RuntimeShape &input_shape, const Scalar *input_data,
- const RuntimeShape *const *output_shapes, Scalar *const *output_data)
-{
- ruy::profiler::ScopeLabel label("Split");
- const int split_dimensions = input_shape.DimensionsCount();
- int axis = params.axis < 0 ? params.axis + split_dimensions : params.axis;
- int outputs_count = params.num_split;
- TFLITE_DCHECK_LT(axis, split_dimensions);
-
- int64_t split_size = 0;
- for (int i = 0; i < outputs_count; i++)
- {
- TFLITE_DCHECK_EQ(output_shapes[i]->DimensionsCount(), split_dimensions);
- for (int j = 0; j < split_dimensions; j++)
- {
- if (j != axis)
- {
- MatchingDim(*output_shapes[i], j, input_shape, j);
- }
- }
- split_size += output_shapes[i]->Dims(axis);
- }
- TFLITE_DCHECK_EQ(split_size, input_shape.Dims(axis));
- int64_t outer_size = 1;
- for (int i = 0; i < axis; ++i)
- {
- outer_size *= input_shape.Dims(i);
- }
- // For all output arrays,
- // FlatSize() = outer_size * Dims(axis) * base_inner_size;
- int64_t base_inner_size = 1;
- for (int i = axis + 1; i < split_dimensions; ++i)
- {
- base_inner_size *= input_shape.Dims(i);
- }
-
- const Scalar *input_ptr = input_data;
- for (int k = 0; k < outer_size; k++)
- {
- for (int i = 0; i < outputs_count; ++i)
- {
- const int copy_size = output_shapes[i]->Dims(axis) * base_inner_size;
- memcpy(output_data[i] + k * copy_size, input_ptr, copy_size * sizeof(Scalar));
- input_ptr += copy_size;
- }
- }
-}
-
-inline int NodeOffset(int b, int h, int w, int height, int width)
-{
- return (b * height + h) * width + w;
-}
-
-inline void LocalResponseNormalization(const tflite::LocalResponseNormalizationParams &op_params,
- const RuntimeShape &input_shape, const float *input_data,
- const RuntimeShape &output_shape, float *output_data)
-{
- const int trailing_dim = input_shape.DimensionsCount() - 1;
- const int outer_size = MatchingFlatSizeSkipDim(input_shape, trailing_dim, output_shape);
- const int depth = MatchingDim(input_shape, trailing_dim, output_shape, trailing_dim);
-
- for (int i = 0; i < outer_size; ++i)
- {
- for (int c = 0; c < depth; ++c)
- {
- const int begin_input_c = std::max(0, static_cast<int>(c - op_params.range));
- const int end_input_c = std::min(depth, static_cast<int>(c + op_params.range));
- float accum = 0.f;
- for (int input_c = begin_input_c; input_c < end_input_c; ++input_c)
- {
- const float input_val = input_data[i * depth + input_c];
- accum += input_val * input_val;
- }
- const float multiplier = std::pow(op_params.bias + op_params.alpha * accum, -op_params.beta);
- output_data[i * depth + c] = input_data[i * depth + c] * multiplier;
- }
- }
-}
-
-inline void Dequantize(const RuntimeShape &input_shape, const Eigen::half *input_data,
- const RuntimeShape &output_shape, float *output_data)
-{
- const int flat_size = MatchingFlatSize(input_shape, output_shape);
- for (int i = 0; i < flat_size; i++)
- {
- output_data[i] = static_cast<float>(input_data[i]);
- }
-}
-
-inline void FakeQuant(const tflite::FakeQuantParams &op_params, const RuntimeShape &input_shape,
- const float *input_data, const RuntimeShape &output_shape, float *output_data)
-{
- ruy::profiler::ScopeLabel label("FakeQuant");
- float rmin = op_params.minmax.min;
- float rmax = op_params.minmax.max;
- int num_bits = op_params.num_bits;
- // 0 should always be a representable value. Let's assume that the initial
- // min,max range contains 0.
- TFLITE_DCHECK_LE(rmin, 0.0f);
- TFLITE_DCHECK_GE(rmax, 0.0f);
- TFLITE_DCHECK_LT(rmin, rmax);
-
- // Code matches tensorflow's FakeQuantWithMinMaxArgsFunctor.
- int quant_min = 0;
- int quant_max = (1 << num_bits) - 1;
- float nudged_min, nudged_max, nudged_scale;
- NudgeQuantizationRange(rmin, rmax, quant_min, quant_max, &nudged_min, &nudged_max, &nudged_scale);
- const int flat_size = MatchingFlatSize(input_shape, output_shape);
- FakeQuantizeArray(nudged_scale, nudged_min, nudged_max, input_data, output_data, flat_size);
-}
-
-// Common subroutine for both `GatherNd` and `GatherNdString`.
-struct GatherNdHelperResult
-{
- int n_slices;
- int slice_size;
- int indices_nd;
- std::vector<int> dims_to_count;
-};
-
-// Returns common values being used on both `GatherNd` and `GatherNdString`.
-inline GatherNdHelperResult GatherNdHelper(const RuntimeShape &params_shape,
- const RuntimeShape &indices_shape)
-{
- GatherNdHelperResult ret;
- ret.n_slices = 1;
- ret.slice_size = 1;
- const int indices_dims = indices_shape.DimensionsCount();
- ret.indices_nd = indices_shape.Dims(indices_dims - 1);
- const int params_dims = params_shape.DimensionsCount();
- for (int i = 0; i < indices_dims - 1; ++i)
- {
- ret.n_slices *= indices_shape.Dims(i);
- }
- for (int i = ret.indices_nd; i < params_dims; ++i)
- {
- ret.slice_size *= params_shape.Dims(i);
- }
-
- int remain_flat_size = params_shape.FlatSize();
- ret.dims_to_count = std::vector<int>(ret.indices_nd, 0);
- for (int i = 0; i < ret.indices_nd; ++i)
- {
- ret.dims_to_count[i] = remain_flat_size / params_shape.Dims(i);
- remain_flat_size = ret.dims_to_count[i];
- }
-
- return ret;
-}
-
-template <typename ParamsT, typename IndicesT = int32>
-inline void GatherNd(const RuntimeShape &params_shape, const ParamsT *params_data,
- const RuntimeShape &indices_shape, const IndicesT *indices_data,
- const RuntimeShape &output_shape, ParamsT *output_data)
-{
- ruy::profiler::ScopeLabel label("GatherNd");
-
- const GatherNdHelperResult res = GatherNdHelper(params_shape, indices_shape);
- for (int i = 0; i < res.n_slices; ++i)
- {
- int from_pos = 0;
- for (int j = 0; j < res.indices_nd; ++j)
- {
- from_pos += indices_data[i * res.indices_nd + j] * res.dims_to_count[j];
- }
- std::memcpy(output_data + i * res.slice_size, params_data + from_pos,
- sizeof(ParamsT) * res.slice_size);
- }
-}
-
-#ifndef TF_LITE_STATIC_MEMORY
-template <typename IndicesT = int32>
-inline void GatherNdString(const RuntimeShape &params_shape, const TfLiteTensor *params_data,
- const RuntimeShape &indices_shape, const IndicesT *indices_data,
- const RuntimeShape &output_shape, TfLiteTensor *output_data)
-{
- ruy::profiler::ScopeLabel label("GatherNdString");
-
- const GatherNdHelperResult res = GatherNdHelper(params_shape, indices_shape);
- DynamicBuffer buffer;
- for (int i = 0; i < res.n_slices; ++i)
- {
- int from_pos = 0;
- for (int j = 0; j < res.indices_nd; ++j)
- {
- from_pos += indices_data[i * res.indices_nd + j] * res.dims_to_count[j];
- }
- for (int j = 0; j < res.slice_size; ++j)
- {
- buffer.AddString(GetString(params_data, from_pos + j));
- }
- }
- buffer.WriteToTensor(output_data, /*new_shape=*/nullptr);
-}
-#endif
-
-template <typename IndicesT, typename UpdatesT>
-inline void ScatterNd(const RuntimeShape &indices_shape, const IndicesT *indices_data,
- const RuntimeShape &updates_shape, const UpdatesT *updates_data,
- const RuntimeShape &output_shape, UpdatesT *output_data)
-{
- ruy::profiler::ScopeLabel label("ScatterNd");
-
- int n_slices = 1;
- int slice_size = 1;
- const int outer_dims = indices_shape.DimensionsCount() - 1;
- const int indices_nd = indices_shape.Dims(outer_dims);
- const int updates_dims = updates_shape.DimensionsCount();
- for (int i = 0; i < outer_dims; ++i)
- {
- n_slices *= indices_shape.Dims(i);
- }
- for (int i = outer_dims; i < updates_dims; ++i)
- {
- slice_size *= updates_shape.Dims(i);
- }
-
- int output_flat_size = output_shape.FlatSize();
- int remain_flat_size = output_flat_size;
- std::vector<int> dims_to_count(indices_nd, 0);
- for (int i = 0; i < indices_nd; ++i)
- {
- dims_to_count[i] = remain_flat_size / output_shape.Dims(i);
- remain_flat_size = dims_to_count[i];
- }
-
- memset(output_data, 0, sizeof(UpdatesT) * output_flat_size);
- for (int i = 0; i < n_slices; ++i)
- {
- int to_pos = 0;
- for (int j = 0; j < indices_nd; ++j)
- {
- IndicesT idx = indices_data[i * indices_nd + j];
- TFLITE_DCHECK(0 <= idx && idx < output_shape.Dims(j));
- to_pos += idx * dims_to_count[j];
- }
- for (int j = 0; j < slice_size; j++)
- {
- output_data[to_pos + j] += updates_data[i * slice_size + j];
- }
- }
-}
-
-template <typename T>
-inline void Slice(const tflite::SliceParams &op_params, const RuntimeShape &input_shape,
- const RuntimeShape &output_shape, SequentialTensorWriter<T> *writer)
-{
- const RuntimeShape ext_shape = RuntimeShape::ExtendedShape(5, input_shape);
- TFLITE_DCHECK_LE(op_params.begin_count, 5);
- TFLITE_DCHECK_LE(op_params.size_count, 5);
- const int begin_count = op_params.begin_count;
- const int size_count = op_params.size_count;
- // We front-pad the begin and size vectors.
- std::array<int, 5> start;
- std::array<int, 5> stop;
- for (int i = 0; i < 5; ++i)
- {
- int padded_i = 5 - i;
- start[i] = begin_count < padded_i ? 0 : op_params.begin[begin_count - padded_i];
- stop[i] = (size_count < padded_i || op_params.size[size_count - padded_i] == -1)
- ? ext_shape.Dims(i)
- : start[i] + op_params.size[size_count - padded_i];
- }
-
- for (int i0 = start[0]; i0 < stop[0]; ++i0)
- {
- for (int i1 = start[1]; i1 < stop[1]; ++i1)
- {
- for (int i2 = start[2]; i2 < stop[2]; ++i2)
- {
- for (int i3 = start[3]; i3 < stop[3]; ++i3)
- {
- for (int i4 = start[4]; i4 < stop[4]; ++i4)
- {
- writer->Write(Offset(ext_shape, i0, i1, i2, i3, i4));
- }
- }
- }
- }
- }
-}
-
-template <typename T>
-inline void Slice(const tflite::SliceParams &op_params, const RuntimeShape &input_shape,
- const T *input_data, const RuntimeShape &output_shape, T *output_data)
-{
- SequentialTensorWriter<T> writer(input_data, output_data);
- return Slice(op_params, input_shape, output_shape, &writer);
-}
-
-template <typename T>
-inline void Slice(const tflite::SliceParams &op_params, const RuntimeShape &input_shape,
- const TfLiteTensor *input, const RuntimeShape &output_shape, TfLiteTensor *output)
-{
- SequentialTensorWriter<T> writer(input, output);
- return Slice(op_params, input_shape, output_shape, &writer);
-}
-
-template <typename T>
-void Minimum(const RuntimeShape &input1_shape, const T *input1_data, const T *input2_data,
- const RuntimeShape &output_shape, T *output_data)
-{
- const int flat_size = MatchingFlatSize(input1_shape, output_shape);
-
- auto min_value = input2_data[0];
- for (int i = 0; i < flat_size; i++)
- {
- output_data[i] = input1_data[i] > min_value ? min_value : input1_data[i];
- }
-}
-
-// Convenience version that allows, for example, generated-code calls to be
-// the same as other binary ops.
-template <typename T>
-inline void Minimum(const RuntimeShape &input1_shape, const T *input1_data, const RuntimeShape &,
- const T *input2_data, const RuntimeShape &output_shape, T *output_data)
-{
- // Drop shape of second input: not needed.
- Minimum(input1_shape, input1_data, input2_data, output_shape, output_data);
-}
-
-template <typename T>
-void Maximum(const RuntimeShape &input1_shape, const T *input1_data, const T *input2_data,
- const RuntimeShape &output_shape, T *output_data)
-{
- const int flat_size = MatchingFlatSize(input1_shape, output_shape);
-
- auto max_value = input2_data[0];
- for (int i = 0; i < flat_size; i++)
- {
- output_data[i] = input1_data[i] < max_value ? max_value : input1_data[i];
- }
-}
-
-// Convenience version that allows, for example, generated-code calls to be
-// the same as other binary ops.
-template <typename T>
-inline void Maximum(const RuntimeShape &input1_shape, const T *input1_data, const RuntimeShape &,
- const T *input2_data, const RuntimeShape &output_shape, T *output_data)
-{
- // Drop shape of second input: not needed.
- Maximum(input1_shape, input1_data, input2_data, output_shape, output_data);
-}
-
-template <typename T1, typename T2, typename T3>
-void ArgMax(const RuntimeShape &input1_shape, const T1 *input1_data, const T3 *input2_data,
- const RuntimeShape &output_shape, T2 *output_data)
-{
- ArgMinMax(input1_shape, input1_data, input2_data, output_shape, output_data, std::greater<T1>());
-}
-
-// Convenience version that allows, for example, generated-code calls to be
-// the same as other binary ops.
-template <typename T1, typename T2, typename T3>
-inline void ArgMax(const RuntimeShape &input1_shape, const T1 *input1_data,
- const RuntimeShape &input2_shape, const T3 *input2_data,
- const RuntimeShape &output_shape, T2 *output_data)
-{
- // Drop shape of second input: not needed.
- ArgMax(input1_shape, input1_data, input2_data, output_shape, output_data);
-}
-
-template <typename D, typename T>
-void Select(const RuntimeShape &input_condition_shape, const D *input_condition_data,
- const RuntimeShape &input_x_shape, const T *input_x_data,
- const RuntimeShape &input_y_shape, const T *input_y_data,
- const RuntimeShape &output_shape, T *output_data)
-{
- int64_t flatsize;
- // Allow select operator executions on mixed scalar tensors and one element
- // tensors.
- if (input_condition_shape.FlatSize() == 1 && input_x_shape.FlatSize() == 1 &&
- input_y_shape.FlatSize() == 1 && output_shape.FlatSize() == 1)
- {
- flatsize = 1;
- }
- else
- {
- flatsize = MatchingFlatSize(input_condition_shape, input_x_shape, input_y_shape, output_shape);
- }
- for (int64_t i = 0; i < flatsize; ++i)
- {
- output_data[i] = input_condition_data[i] ? input_x_data[i] : input_y_data[i];
- }
-}
-
-template <typename D, typename T>
-void RankOneSelect(const RuntimeShape &input_condition_shape, const D *input_condition_data,
- const RuntimeShape &input_x_shape, const T *input_x_data,
- const RuntimeShape &input_y_shape, const T *input_y_data,
- const RuntimeShape &output_shape, T *output_data)
-{
- const int64_t outer_size = input_condition_shape.FlatSize();
- int64_t inner_size;
- if (input_condition_shape.DimensionsCount() == 0)
- {
- inner_size = MatchingFlatSize(input_x_shape, input_y_shape, output_shape);
- }
- else
- {
- TFLITE_DCHECK_EQ(MatchingDim(input_x_shape, 0, input_y_shape, 0, output_shape, 0), outer_size);
- inner_size = MatchingFlatSizeSkipDim(input_x_shape, 0, input_y_shape, output_shape);
- }
-
- int64_t offset = 0;
- for (int64_t i = 0; i < outer_size; i++)
- {
- const T *input_data = input_condition_data[i] ? input_x_data : input_y_data;
- memcpy(output_data + offset, input_data + offset, inner_size * sizeof(T));
- offset += inner_size;
- }
-}
-
-template <typename D, typename T>
-void BroadcastSelect4DSlow(const RuntimeShape &input_condition_shape, const D *input_condition_data,
- const RuntimeShape &input_x_shape, const T *input_x_data,
- const RuntimeShape &input_y_shape, const T *input_y_data,
- const RuntimeShape &output_shape, T *output_data)
-{
- TFLITE_DCHECK_LE(input_condition_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(input_x_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(input_y_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(output_shape.DimensionsCount(), 4);
-
- const RuntimeShape extended_output_shape = RuntimeShape::ExtendedShape(4, output_shape);
-
- NdArrayDesc<4> desc_condition;
- NdArrayDesc<4> desc_x;
- NdArrayDesc<4> desc_y;
- NdArrayDescsForElementwiseBroadcast(input_condition_shape, input_x_shape, input_y_shape,
- &desc_condition, &desc_x, &desc_y);
-
- // In Tensorflow, the dimensions are canonically named (batch_number, row,
- // col, channel), with extents (batches, height, width, depth), with the
- // trailing dimension changing most rapidly (channels has the smallest
- // stride, typically 1 element).
- //
- // In generated C code, we store arrays with the dimensions reversed. The
- // first dimension has smallest stride.
- //
- // We name our variables by their Tensorflow convention, but generate C code
- // nesting loops such that the innermost loop has the smallest stride for
- // the best cache behavior.
- for (int b = 0; b < extended_output_shape.Dims(0); ++b)
- {
- for (int y = 0; y < extended_output_shape.Dims(1); ++y)
- {
- for (int x = 0; x < extended_output_shape.Dims(2); ++x)
- {
- for (int c = 0; c < extended_output_shape.Dims(3); ++c)
- {
- const int condition_index = SubscriptToIndex(desc_condition, b, y, x, c);
- const int x_index = SubscriptToIndex(desc_x, b, y, x, c);
- const int y_index = SubscriptToIndex(desc_y, b, y, x, c);
- output_data[Offset(extended_output_shape, b, y, x, c)] =
- input_condition_data[condition_index] ? input_x_data[x_index] : input_y_data[y_index];
- }
- }
- }
- }
-}
-
-template <typename D, typename T>
-void SelectTrueCoords(const RuntimeShape &input_condition_shape, const D *input_condition_data,
- T *output_data)
-{
- const size_t size = input_condition_shape.FlatSize();
- if (size == 0)
- {
- // Dimension is zero, in which case we don't need to output.
- return;
- }
- const size_t cond_rank = input_condition_shape.DimensionsCount();
-
- std::vector<int> dims_to_count(cond_rank, 0);
- int cur_flat_size = size;
- for (int i = 0; i < cond_rank; ++i)
- {
- dims_to_count[i] = cur_flat_size / input_condition_shape.Dims(i);
- cur_flat_size = dims_to_count[i];
- }
-
- int output_index = 0;
- for (int i = 0; i < size; ++i)
- {
- if (input_condition_data[i])
- {
- // Insert the coordinate of the current item (row major) into output.
- int flat_index = i;
- for (int j = 0; j < cond_rank; ++j)
- {
- int coord_j = flat_index / dims_to_count[j];
- output_data[output_index * cond_rank + j] = coord_j;
- flat_index %= dims_to_count[j];
- }
- output_index++;
- }
- }
-}
-
-// For easy implementation, the indices is always a vector of size-4 vectors.
-template <typename T, typename TI>
-inline void SparseToDense(const std::vector<std::vector<TI>> &indices, const T *values,
- T default_value, bool value_is_scalar,
- const RuntimeShape &unextended_output_shape, T *output_data)
-{
- TFLITE_DCHECK_LE(unextended_output_shape.DimensionsCount(), 4);
- const RuntimeShape output_shape = RuntimeShape::ExtendedShape(4, unextended_output_shape);
- const int value_count = indices.size();
-
- // First fill the output_data with default value.
- const int num_elements = output_shape.FlatSize();
- for (int i = 0; i < num_elements; ++i)
- {
- output_data[i] = default_value;
- }
-
- // Special handle for value is scalar case to avoid checking the boolean
- // condition within the loop every time.
- if (value_is_scalar)
- {
- for (int i = 0; i < value_count; ++i)
- {
- const std::vector<TI> &index = indices[i];
- TFLITE_DCHECK_EQ(index.size(), 4);
- const T value = *values; // just use the first value.
- output_data[Offset(output_shape, index[0], index[1], index[2], index[3])] = value;
- }
- return;
- }
-
- // Go through the values and indices to fill the sparse values.
- for (int i = 0; i < value_count; ++i)
- {
- const std::vector<TI> &index = indices[i];
- TFLITE_DCHECK_EQ(index.size(), 4);
- const T value = values[i];
- output_data[Offset(output_shape, index[0], index[1], index[2], index[3])] = value;
- }
-}
-
-template <typename T>
-inline void Pow(const RuntimeShape &input1_shape, const T *input1_data,
- const RuntimeShape &input2_shape, const T *input2_data,
- const RuntimeShape &output_shape, T *output_data)
-{
- const int flat_size = MatchingFlatSize(input1_shape, input2_shape, output_shape);
- for (int i = 0; i < flat_size; ++i)
- {
- output_data[i] = std::pow(input1_data[i], input2_data[i]);
- }
-}
-
-template <typename T>
-inline void BroadcastPow4DSlow(const RuntimeShape &unextended_input1_shape, const T *input1_data,
- const RuntimeShape &unextended_input2_shape, const T *input2_data,
- const RuntimeShape &unextended_output_shape, T *output_data)
-{
- TFLITE_DCHECK_LE(unextended_input1_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_input2_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_output_shape.DimensionsCount(), 4);
- const RuntimeShape output_shape = RuntimeShape::ExtendedShape(4, unextended_output_shape);
-
- NdArrayDesc<4> desc1;
- NdArrayDesc<4> desc2;
- NdArrayDescsForElementwiseBroadcast(unextended_input1_shape, unextended_input2_shape, &desc1,
- &desc2);
-
- for (int b = 0; b < output_shape.Dims(0); ++b)
- {
- for (int y = 0; y < output_shape.Dims(1); ++y)
- {
- for (int x = 0; x < output_shape.Dims(2); ++x)
- {
- for (int c = 0; c < output_shape.Dims(3); ++c)
- {
- auto out_idx = Offset(output_shape, b, y, x, c);
- auto in1_idx = SubscriptToIndex(desc1, b, y, x, c);
- auto in2_idx = SubscriptToIndex(desc2, b, y, x, c);
- auto in1_val = input1_data[in1_idx];
- auto in2_val = input2_data[in2_idx];
- output_data[out_idx] = std::pow(in1_val, in2_val);
- }
- }
- }
- }
-}
-
-template <typename Scalar>
-void Reverse(int axis, const RuntimeShape &input_shape, const Scalar *input_data,
- const RuntimeShape &output_shape, Scalar *output_data)
-{
- ruy::profiler::ScopeLabel label("Reverse");
-
- int outer_size = 1;
- for (int i = 0; i < axis; ++i)
- {
- outer_size *= input_shape.Dims(i);
- }
-
- int copy_size = 1;
- for (int i = axis + 1; i < input_shape.DimensionsCount(); ++i)
- {
- copy_size *= input_shape.Dims(i);
- }
-
- const int dims_at_axis = input_shape.Dims(axis);
- for (int i = 0; i < outer_size; ++i)
- {
- for (int j = 0; j < dims_at_axis; ++j)
- {
- const int start_pos = (i * dims_at_axis + j) * copy_size;
- Scalar *output_ptr = output_data + start_pos;
- int loc = (i * dims_at_axis + dims_at_axis - j - 1) * copy_size;
- memcpy(output_ptr, input_data + loc, copy_size * sizeof(Scalar));
- }
- }
-}
-
-template <typename Scalar, typename TS>
-void ReverseSequence(const TS *seq_lengths, const int seq_dim, const int batch_dim,
- const RuntimeShape &input_shape, const Scalar *input_data,
- const RuntimeShape &output_shape, Scalar *output_data)
-{
- ruy::profiler::ScopeLabel label("ReverseSequence");
-
- int outer_size = 1;
- int outer_dim = std::min(batch_dim, seq_dim);
- int medium_dim = std::max(batch_dim, seq_dim);
- for (int i = 0; i < outer_dim; ++i)
- {
- outer_size *= input_shape.Dims(i);
- }
-
- int medium_size = 1;
- for (int i = outer_dim + 1; i < medium_dim; ++i)
- {
- medium_size *= input_shape.Dims(i);
- }
-
- int copy_size = 1;
- for (int i = medium_dim + 1; i < input_shape.DimensionsCount(); ++i)
- {
- copy_size *= input_shape.Dims(i);
- }
-
- const int dims_at_outer_dim = input_shape.Dims(outer_dim);
- const int dims_at_medium_dim = input_shape.Dims(medium_dim);
-
- Scalar *output_ptr;
- if (batch_dim > seq_dim)
- {
- for (int i = 0; i < outer_size; ++i)
- {
- for (int j = 0; j < dims_at_outer_dim; ++j)
- {
- const int in_pos_base = (i * dims_at_outer_dim + j) * medium_size;
- for (int p = 0; p < medium_size; ++p)
- {
- for (int q = 0; q < dims_at_medium_dim; ++q)
- {
- const int in_pos = ((in_pos_base + p) * dims_at_medium_dim + q) * copy_size;
- const Scalar *in_ptr = input_data + in_pos;
- int sl = seq_lengths[q] - 1;
- if (j > sl)
- {
- output_ptr = output_data + in_pos;
- }
- else
- {
- const int out_pos_base = (i * dims_at_outer_dim + sl - j) * medium_size;
- const int out_pos = ((out_pos_base + p) * dims_at_medium_dim + q) * copy_size;
- output_ptr = output_data + out_pos;
- }
- memcpy(output_ptr, in_ptr, copy_size * sizeof(Scalar));
- }
- }
- }
- }
- }
- else if (batch_dim < seq_dim)
- {
- for (int i = 0; i < outer_size; ++i)
- {
- for (int j = 0; j < dims_at_outer_dim; ++j)
- {
- const int in_pos_base = (i * dims_at_outer_dim + j) * medium_size;
- int sl = seq_lengths[j] - 1;
- const int out_pos_base = (i * dims_at_outer_dim + j) * medium_size;
- for (int p = 0; p < medium_size; ++p)
- {
- for (int q = 0; q < dims_at_medium_dim; ++q)
- {
- const int in_pos = ((in_pos_base + p) * dims_at_medium_dim + q) * copy_size;
- const Scalar *in_ptr = input_data + in_pos;
- if (q > sl)
- {
- output_ptr = output_data + in_pos;
- }
- else
- {
- const int out_pos = ((out_pos_base + p) * dims_at_medium_dim + sl - q) * copy_size;
- output_ptr = output_data + out_pos;
- }
- memcpy(output_ptr, in_ptr, copy_size * sizeof(Scalar));
- }
- }
- }
- }
- }
-}
-
-template <typename T>
-inline void SegmentSum(const RuntimeShape &input_shape, const T *input_data,
- const RuntimeShape &segment_ids_shape, const int32_t *segment_ids_data,
- const RuntimeShape &output_shape, T *output_data)
-{
- const int segment_flat_size = MatchingFlatSizeSkipDim(input_shape, 0, output_shape);
-
- memset(output_data, 0, sizeof(T) * output_shape.FlatSize());
-
- for (int i = 0; i < input_shape.Dims(0); i++)
- {
- int output_index = segment_ids_data[i];
- for (int j = 0; j < segment_flat_size; ++j)
- {
- output_data[output_index * segment_flat_size + j] += input_data[i * segment_flat_size + j];
- }
- }
-}
-
-} // namespace reference_ops
-} // namespace tflite
-
-#endif // LUCI_INTERPRETER_PAL_REFERENCE_OPS_H
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALElu.h b/onert-micro/luci-interpreter/pal/common/PALAbs.h
index fc8c573f8..a1f5ae374 100644
--- a/onert-micro/luci-interpreter/pal/cmsisnn/PALElu.h
+++ b/onert-micro/luci-interpreter/pal/common/PALAbs.h
@@ -1,6 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,20 +14,22 @@
* limitations under the License.
*/
-#ifndef LUCI_INTERPRETER_PAL_ELU_H
-#define LUCI_INTERPRETER_PAL_ELU_H
+#ifndef LUCI_INTERPRETER_PAL_ABS_H
+#define LUCI_INTERPRETER_PAL_ABS_H
-#include <tensorflow/lite/kernels/internal/reference/elu.h>
+#include <cmath>
namespace luci_interpreter_pal
{
-static inline void Elu(const tflite::RuntimeShape &input_shape, const float *input_data,
- const tflite::RuntimeShape &output_shape, float *output_data)
+inline void Abs(const int flat_size, const float *input_data, float *output_data)
{
- tflite::reference_ops::Elu(input_shape, input_data, output_shape, output_data);
+ for (int i = 0; i < flat_size; ++i)
+ {
+ output_data[i] = std::abs(input_data[i]);
+ }
}
} // namespace luci_interpreter_pal
-#endif // LUCI_INTERPRETER_PAL_ELU_H
+#endif // LUCI_INTERPRETER_PAL_ABS_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALAddCommon.h b/onert-micro/luci-interpreter/pal/common/PALAddCommon.h
new file mode 100644
index 000000000..57f9b107e
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/PALAddCommon.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_ADD_COMMON_H
+#define LUCI_INTERPRETER_PAL_ADD_COMMON_H
+
+#include "Params.h"
+#include "PALUtils.h"
+#include "ProcessBroadcastShapes.h"
+
+namespace luci_interpreter_pal
+{
+
+// TODO: check if there real activation value
+template <typename T>
+inline void Add(const ArithmeticParams &params, const int flat_size, const T *input1_data,
+ const T *input2_data, T *output_data)
+{
+ T activation_min, activation_max;
+ getActivationParams(params, &activation_min, &activation_max);
+
+ for (int i = 0; i < flat_size; ++i)
+ output_data[i] =
+ std::min(std::max(input1_data[i] + input2_data[i], activation_min), activation_max);
+}
+
+template <typename T>
+inline void
+BroadcastAdd4DSlow(const ArithmeticParams &params,
+ const luci_interpreter::RuntimeShape &input1_shape, const T *input1_data,
+ const luci_interpreter::RuntimeShape &input2_shape, const T *input2_data,
+ const luci_interpreter::RuntimeShape &output_shape, T *output_data)
+{
+ NdArrayDesc<4> desc1;
+ NdArrayDesc<4> desc2;
+ NdArrayDescsForElementwiseBroadcast(input1_shape, input2_shape, &desc1, &desc2);
+ const luci_interpreter::RuntimeShape extended_output_shape =
+ luci_interpreter::RuntimeShape::extendedShape(4, output_shape);
+
+ T activation_min, activation_max;
+ getActivationParams(params, &activation_min, &activation_max);
+
+ // In Tensorflow, the dimensions are canonically named (batch_number, row,
+ // col, channel), with extents (batches, height, width, depth), with the
+ // trailing dimension changing most rapidly (channels has the smallest stride,
+ // typically 1 element).
+ //
+ // In generated C code, we store arrays with the dimensions reversed. The
+ // first dimension has smallest stride.
+ //
+ // We name our variables by their Tensorflow convention, but generate C code
+ // nesting loops such that the innermost loop has the smallest stride for the
+ // best cache behavior.
+ for (int b = 0; b < extended_output_shape.dims(0); ++b)
+ {
+ for (int y = 0; y < extended_output_shape.dims(1); ++y)
+ {
+ for (int x = 0; x < extended_output_shape.dims(2); ++x)
+ {
+ for (int c = 0; c < extended_output_shape.dims(3); ++c)
+ {
+ const int output_data_offset =
+ ((b * extended_output_shape.dims(1) + y) * extended_output_shape.dims(2) + x) *
+ extended_output_shape.dims(3) +
+ c;
+
+ output_data[output_data_offset] =
+ std::min(std::max(input1_data[subscriptToIndex(desc1, b, y, x, c)] +
+ input2_data[subscriptToIndex(desc2, b, y, x, c)],
+ activation_min),
+ activation_max);
+ }
+ }
+ }
+ }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_ADD_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALAddN.h b/onert-micro/luci-interpreter/pal/common/PALAddN.h
new file mode 100644
index 000000000..63fbc03c0
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/PALAddN.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2020 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_ADD_N_H
+#define LUCI_INTERPRETER_PAL_ADD_N_H
+
+#include "Params.h"
+#include "PALUtils.h"
+
+namespace luci_interpreter_pal
+{
+
+// T is expected to be either float or int.
+template <typename T>
+inline void AddN(const size_t flat_size, const size_t num_inputs, const T *const *input_data,
+ T *output_data)
+{
+ // All inputs and output should have the same shape, this is checked during
+ // Prepare stage.
+ for (size_t i = 0; i < flat_size; ++i)
+ {
+ T x = 0;
+ for (size_t j = 0; j < num_inputs; ++j)
+ {
+ x += input_data[j][i];
+ }
+ output_data[i] = x;
+ }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_ADD_N_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALArgMinMax.h b/onert-micro/luci-interpreter/pal/common/PALArgMinMax.h
new file mode 100644
index 000000000..58602d8b9
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/PALArgMinMax.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_ARG_MIN_MAX_H
+#define LUCI_INTERPRETER_PAL_ARG_MIN_MAX_H
+
+#include "Params.h"
+#include "PALUtils.h"
+
+namespace luci_interpreter_pal
+{
+
+template <typename T1, typename T2, typename T3, typename Cmp>
+void ArgMinMax(const luci_interpreter::RuntimeShape &input1_shape, const T1 *input1_data,
+ const T3 *input2_data, const luci_interpreter::RuntimeShape &output_shape,
+ T2 *output_data, const Cmp &cmp)
+{
+ int axis = input2_data[0];
+ if (axis < 0)
+ {
+ axis += input1_shape.dimensionsCount();
+ }
+ const int axis_size = input1_shape.dims(axis);
+
+ int outer_size = 1;
+ for (int i = 0; i < axis; ++i)
+ {
+ outer_size *= input1_shape.dims(i);
+ }
+
+ int inner_size = 1;
+ const int dims_count = input1_shape.dimensionsCount();
+ for (int i = axis + 1; i < dims_count; ++i)
+ {
+ inner_size *= input1_shape.dims(i);
+ }
+ for (int outer = 0; outer < outer_size; ++outer)
+ {
+ for (int inner = 0; inner < inner_size; ++inner)
+ {
+ auto min_max_value = input1_data[outer * axis_size * inner_size + inner];
+ T2 min_max_index = 0;
+ for (int i = 1; i < axis_size; ++i)
+ {
+ const auto &curr_value = input1_data[(outer * axis_size + i) * inner_size + inner];
+ if (cmp(curr_value, min_max_value))
+ {
+ min_max_value = curr_value;
+ min_max_index = static_cast<T2>(i);
+ }
+ }
+ output_data[outer * inner_size + inner] = min_max_index;
+ }
+ }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_ARG_MIN_MAX_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALAveragePool2DCommon.h b/onert-micro/luci-interpreter/pal/common/PALAveragePool2DCommon.h
new file mode 100644
index 000000000..ec6bb55b5
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/PALAveragePool2DCommon.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2020 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_AVERAGE_POOL_2D_COMMON_H
+#define LUCI_INTERPRETER_PAL_AVERAGE_POOL_2D_COMMON_H
+
+#include "Params.h"
+#include "PALUtils.h"
+
+namespace luci_interpreter_pal
+{
+
+// TODO: reduce code duplication with MaxPool
+inline void AveragePool(const PoolParams &params, const luci_interpreter::RuntimeShape &input_shape,
+ const float *input_data, const luci_interpreter::RuntimeShape &output_shape,
+ float *output_data)
+{
+ const int batches = input_shape.dims(0);
+ const int depth = output_shape.dims(3);
+ const int input_height = input_shape.dims(1);
+ const int input_width = input_shape.dims(2);
+ const int output_height = output_shape.dims(1);
+ const int output_width = output_shape.dims(2);
+ const int stride_height = params.stride_height;
+ const int stride_width = params.stride_width;
+ for (int batch = 0; batch < batches; ++batch)
+ {
+ for (int out_y = 0; out_y < output_height; ++out_y)
+ {
+ for (int out_x = 0; out_x < output_width; ++out_x)
+ {
+ for (int channel = 0; channel < depth; ++channel)
+ {
+ const int in_x_origin = (out_x * stride_width) - params.padding_values.width;
+ const int in_y_origin = (out_y * stride_height) - params.padding_values.height;
+ // Compute the boundaries of the filter region clamped so as to
+ // ensure that the filter window fits in the input array.
+ const int filter_x_start = std::max(0, -in_x_origin);
+ const int filter_x_end = std::min(params.filter_width, input_width - in_x_origin);
+ const int filter_y_start = std::max(0, -in_y_origin);
+ const int filter_y_end = std::min(params.filter_height, input_height - in_y_origin);
+
+ float total = 0.f;
+ float filter_count = 0;
+
+ for (int filter_y = filter_y_start; filter_y < filter_y_end; ++filter_y)
+ {
+ for (int filter_x = filter_x_start; filter_x < filter_x_end; ++filter_x)
+ {
+ const int in_x = in_x_origin + filter_x;
+ const int in_y = in_y_origin + filter_y;
+
+ const int input_data_offset =
+ ((batch * input_shape.dims(1) + in_y) * input_shape.dims(2) + in_x) *
+ input_shape.dims(3) +
+ channel;
+
+ total += input_data[input_data_offset];
+ filter_count++;
+ }
+ }
+ const int output_data_offset =
+ ((batch * output_shape.dims(1) + out_y) * output_shape.dims(2) + out_x) *
+ output_shape.dims(3) +
+ channel;
+
+ assert(filter_count != 0);
+ const float average = total / filter_count;
+
+ output_data[output_data_offset] =
+ std::min(std::max(average, params.float_activation_min), params.float_activation_max);
+ }
+ }
+ }
+ }
+}
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_AVERAGE_POOL_2D_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALComparisons.h b/onert-micro/luci-interpreter/pal/common/PALComparisons.h
new file mode 100644
index 000000000..bb855a1ad
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/PALComparisons.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_COMPARISONS_H
+#define LUCI_INTERPRETER_PAL_COMPARISONS_H
+
+#include "Params.h"
+#include "ProcessBroadcastShapes.h"
+#include "PALUtils.h"
+
+namespace luci_interpreter_pal
+{
+namespace
+{
+
+struct BroadcastComparison4DSlowCommon
+{
+ const luci_interpreter::RuntimeShape output_shape;
+ NdArrayDesc<4> desc1;
+ NdArrayDesc<4> desc2;
+};
+
+inline BroadcastComparison4DSlowCommon
+BroadcastComparison4DSlowPreprocess(const luci_interpreter::RuntimeShape &unextended_input1_shape,
+ const luci_interpreter::RuntimeShape &unextended_input2_shape,
+ const luci_interpreter::RuntimeShape &unextended_output_shape)
+{
+ NdArrayDesc<4> desc1;
+ NdArrayDesc<4> desc2;
+ NdArrayDescsForElementwiseBroadcast(unextended_input1_shape, unextended_input2_shape, &desc1,
+ &desc2);
+ return {luci_interpreter::RuntimeShape::extendedShape(4, unextended_output_shape), desc1, desc2};
+}
+
+} // namespace
+
+template <typename T> inline bool LessFn(T lhs, T rhs) { return lhs < rhs; }
+template <typename T> inline bool LessEqualFn(T lhs, T rhs) { return lhs <= rhs; }
+template <typename T> inline bool EqualFn(T lhs, T rhs) { return lhs == rhs; }
+template <typename T> inline bool GreaterFn(T lhs, T rhs) { return lhs > rhs; }
+template <typename T> inline bool GreaterEqualFn(T lhs, T rhs) { return lhs >= rhs; }
+template <typename T> inline bool NotEqualFn(T lhs, T rhs) { return lhs != rhs; }
+
+template <typename T>
+inline void ComparisonNoScaling(const int64_t flat_size, const T *input1_data, const T *input2_data,
+ bool *output_data, bool F(T, T))
+{
+ for (int64_t i = 0; i < flat_size; ++i)
+ {
+ output_data[i] = F(input1_data[i], input2_data[i]);
+ }
+}
+
+template <typename T>
+inline void BroadcastComparison4DSlowWithScaling(
+ const ComparisonParams &op_params, const luci_interpreter::RuntimeShape &unextended_input1_shape,
+ const T *input1_data, const luci_interpreter::RuntimeShape &unextended_input2_shape,
+ const T *input2_data, const luci_interpreter::RuntimeShape &unextended_output_shape,
+ bool *output_data, bool F(T, T))
+{
+ const BroadcastComparison4DSlowCommon dims = BroadcastComparison4DSlowPreprocess(
+ unextended_input1_shape, unextended_input2_shape, unextended_output_shape);
+
+ int left_shift = op_params.left_shift;
+ int32_t input1_offset = op_params.input1_offset;
+ int32_t input1_multiplier = op_params.input1_multiplier;
+ int input1_shift = op_params.input1_shift;
+ int32_t input2_offset = op_params.input2_offset;
+ int32_t input2_multiplier = op_params.input2_multiplier;
+ int input2_shift = op_params.input2_shift;
+
+ for (int b = 0; b < dims.output_shape.dims(0); ++b)
+ {
+ for (int y = 0; y < dims.output_shape.dims(1); ++y)
+ {
+ for (int x = 0; x < dims.output_shape.dims(2); ++x)
+ {
+ for (int c = 0; c < dims.output_shape.dims(3); ++c)
+ {
+ const int32_t input1_val =
+ input1_offset + input1_data[subscriptToIndex(dims.desc1, b, y, x, c)];
+ const int32_t input2_val =
+ input2_offset + input2_data[subscriptToIndex(dims.desc2, b, y, x, c)];
+ const int32_t shifted_input1_val = input1_val * (1 << left_shift);
+ const int32_t shifted_input2_val = input2_val * (1 << left_shift);
+ const int32_t scaled_input1_val = multiplyByQuantizedMultiplierSmallerThanOneExp(
+ shifted_input1_val, input1_multiplier, input1_shift);
+ const int32_t scaled_input2_val = multiplyByQuantizedMultiplierSmallerThanOneExp(
+ shifted_input2_val, input2_multiplier, input2_shift);
+
+ const int output_data_offset =
+ ((b * dims.output_shape.dims(1) + y) * dims.output_shape.dims(2) + x) *
+ dims.output_shape.dims(3) +
+ c;
+ output_data[output_data_offset] = F(scaled_input1_val, scaled_input2_val);
+ }
+ }
+ }
+ }
+}
+
+template <typename T>
+inline void ComparisonWithScaling(const ComparisonParams &op_params, const int64_t flat_size,
+ const T *input1_data, const T *input2_data, bool *output_data,
+ bool F(T, T))
+{
+ int left_shift = op_params.left_shift;
+ int32_t input1_offset = op_params.input1_offset;
+ int32_t input1_multiplier = op_params.input1_multiplier;
+ int input1_shift = op_params.input1_shift;
+ int32_t input2_offset = op_params.input2_offset;
+ int32_t input2_multiplier = op_params.input2_multiplier;
+ int input2_shift = op_params.input2_shift;
+
+ for (int64_t i = 0; i < flat_size; ++i)
+ {
+ const int32_t input1_val = input1_offset + input1_data[i];
+ const int32_t input2_val = input2_offset + input2_data[i];
+ const int32_t shifted_input1_val = input1_val * (1 << left_shift);
+ const int32_t shifted_input2_val = input2_val * (1 << left_shift);
+ const int32_t scaled_input1_val = multiplyByQuantizedMultiplierSmallerThanOneExp(
+ shifted_input1_val, input1_multiplier, input1_shift);
+ const int32_t scaled_input2_val = multiplyByQuantizedMultiplierSmallerThanOneExp(
+ shifted_input2_val, input2_multiplier, input2_shift);
+ output_data[i] = F(scaled_input1_val, scaled_input2_val);
+ }
+}
+
+template <typename T>
+inline void BroadcastComparison4DSlowNoScaling(
+ const ComparisonParams &op_params, const luci_interpreter::RuntimeShape &unextended_input1_shape,
+ const T *input1_data, const luci_interpreter::RuntimeShape &unextended_input2_shape,
+ const T *input2_data, const luci_interpreter::RuntimeShape &unextended_output_shape,
+ bool *output_data, bool F(T, T))
+{
+ const BroadcastComparison4DSlowCommon dims = BroadcastComparison4DSlowPreprocess(
+ unextended_input1_shape, unextended_input2_shape, unextended_output_shape);
+
+ for (int b = 0; b < dims.output_shape.dims(0); ++b)
+ {
+ for (int y = 0; y < dims.output_shape.dims(1); ++y)
+ {
+ for (int x = 0; x < dims.output_shape.dims(2); ++x)
+ {
+ for (int c = 0; c < dims.output_shape.dims(3); ++c)
+ {
+ const int output_data_offset =
+ ((b * dims.output_shape.dims(1) + y) * dims.output_shape.dims(2) + x) *
+ dims.output_shape.dims(3) +
+ c;
+ output_data[output_data_offset] =
+ F(input1_data[subscriptToIndex(dims.desc1, b, y, x, c)],
+ input2_data[subscriptToIndex(dims.desc2, b, y, x, c)]);
+ }
+ }
+ }
+ }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_COMPARISONS_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALConcatenation.h b/onert-micro/luci-interpreter/pal/common/PALConcatenation.h
new file mode 100644
index 000000000..2bd385810
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/PALConcatenation.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2020 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_CONCATENATION_H
+#define LUCI_INTERPRETER_PAL_CONCATENATION_H
+
+#include "Params.h"
+#include "PALUtils.h"
+
+namespace luci_interpreter_pal
+{
+
+template <typename Scalar>
+inline void Concatenation(const ConcatenationParams &params,
+ const luci_interpreter::RuntimeShape *const *input_shapes,
+ const Scalar *const *input_data,
+ const luci_interpreter::RuntimeShape &output_shape, Scalar *output_data)
+{
+ int axis = params.axis;
+ int inputs_count = params.inputs_count;
+ const int concat_dimensions = output_shape.dimensionsCount();
+
+ int64_t concat_size = 0;
+ for (int i = 0; i < inputs_count; i++)
+ {
+ concat_size += input_shapes[i]->dims(axis);
+ }
+ int64_t outer_size = 1;
+ for (int i = 0; i < axis; ++i)
+ {
+ outer_size *= output_shape.dims(i);
+ }
+ // For all input arrays,
+ // FlatSize() = outer_size * Dims(axis) * base_inner_size;
+ int64_t base_inner_size = 1;
+ for (int i = axis + 1; i < concat_dimensions; ++i)
+ {
+ base_inner_size *= output_shape.dims(i);
+ }
+
+ Scalar *output_ptr = output_data;
+ for (int k = 0; k < outer_size; k++)
+ {
+ for (int i = 0; i < inputs_count; ++i)
+ {
+ const int copy_size = input_shapes[i]->dims(axis) * base_inner_size;
+ const Scalar *input_ptr = input_data[i] + k * copy_size;
+ memcpy(output_ptr, input_ptr, copy_size * sizeof(Scalar));
+ output_ptr += copy_size;
+ }
+ }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_CONCATENATION_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALConv2DCommon.h b/onert-micro/luci-interpreter/pal/common/PALConv2DCommon.h
new file mode 100644
index 000000000..04b92cd48
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/PALConv2DCommon.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_CONV2D_COMMON_H
+#define LUCI_INTERPRETER_PAL_CONV2D_COMMON_H
+#include "Params.h"
+#include "PALUtils.h"
+
+namespace luci_interpreter_pal
+{
+static inline void Conv(const ConvParams &params, const int32_t *input_shape,
+ const float *input_data, const int32_t *filter_shape,
+ const float *filter_data, const float *bias_data,
+ const int32_t *output_shape, float *output_data)
+{
+ const int stride_width = params.stride_width;
+ const int stride_height = params.stride_height;
+ const int dilation_width_factor = params.dilation_width_factor;
+ const int dilation_height_factor = params.dilation_height_factor;
+ const int pad_width = params.padding_values.width;
+ const int pad_height = params.padding_values.height;
+ const float output_activation_min = params.float_activation_min;
+ const float output_activation_max = params.float_activation_max;
+
+ const auto batches = input_shape[0];
+ const int input_height = input_shape[1];
+ const int input_width = input_shape[2];
+ const int input_depth = input_shape[3];
+ const int output_depth = filter_shape[0];
+ const int filter_height = filter_shape[1];
+ const int filter_width = filter_shape[2];
+ const int output_height = output_shape[1];
+ const int output_width = output_shape[2];
+ for (int batch = 0; batch < batches; ++batch)
+ {
+ for (int out_y = 0; out_y < output_height; ++out_y)
+ {
+ const int in_y_origin = (out_y * stride_height) - pad_height;
+ for (int out_x = 0; out_x < output_width; ++out_x)
+ {
+ const int in_x_origin = (out_x * stride_width) - pad_width;
+ for (int out_channel = 0; out_channel < output_depth; ++out_channel)
+ {
+ float total = 0.f;
+ for (int filter_y = 0; filter_y < filter_height; ++filter_y)
+ {
+ const int in_y = in_y_origin + dilation_height_factor * filter_y;
+ for (int filter_x = 0; filter_x < filter_width; ++filter_x)
+ {
+ const int in_x = in_x_origin + dilation_width_factor * filter_x;
+
+ // Zero padding by omitting the areas outside the image.
+ const bool is_point_inside_image =
+ (in_x >= 0) && (in_x < input_width) && (in_y >= 0) && (in_y < input_height);
+
+ if (!is_point_inside_image)
+ {
+ continue;
+ }
+
+ for (int in_channel = 0; in_channel < input_depth; ++in_channel)
+ {
+ const int input_data_offset =
+ ((batch * input_height + in_y) * input_width + in_x) * input_depth + in_channel;
+
+ const int filter_data_offset =
+ ((out_channel * filter_height + filter_y) * filter_width + filter_x) *
+ input_depth +
+ in_channel;
+
+ const float input_value = input_data[input_data_offset];
+ const float filter_value = filter_data[filter_data_offset];
+ total += (input_value * filter_value);
+ }
+ }
+ }
+ // float bias_value = 0.0f;
+ if (bias_data)
+ {
+ total += bias_data[out_channel];
+ }
+
+ const int output_data_offset =
+ ((batch * output_height + out_y) * output_width + out_x) * output_depth + out_channel;
+
+ output_data[output_data_offset] =
+ std::min(std::max(total, output_activation_min), output_activation_max);
+ }
+ }
+ }
+ }
+}
+
+static inline void Conv(const ConvParams &params, const int32_t *input_shape,
+ const uint8_t *input_data, const int32_t *filter_shape,
+ const uint8_t *filter_data, const int32_t *bias_data,
+ const int32_t *output_shape, uint8_t *output_data)
+{
+ const int stride_width = params.stride_width;
+ const int stride_height = params.stride_height;
+ const int dilation_width_factor = params.dilation_width_factor;
+ const int dilation_height_factor = params.dilation_height_factor;
+ const int pad_width = params.padding_values.width;
+ const int pad_height = params.padding_values.height;
+ const int32_t input_offset = params.input_offset;
+ const int32_t filter_offset = params.weights_offset;
+ const int32_t output_offset = params.output_offset;
+ const int32_t output_multiplier = params.output_multiplier;
+ const int output_shift = params.output_shift;
+ const int32_t output_activation_min = params.quantized_activation_min;
+ const int32_t output_activation_max = params.quantized_activation_max;
+
+ const auto batches = input_shape[0];
+ const int input_height = input_shape[1];
+ const int input_width = input_shape[2];
+ const int input_depth = input_shape[3];
+ const int output_depth = filter_shape[0];
+ const int filter_height = filter_shape[1];
+ const int filter_width = filter_shape[2];
+ const int output_height = output_shape[1];
+ const int output_width = output_shape[2];
+
+ for (int batch = 0; batch < batches; ++batch)
+ {
+ for (int out_y = 0; out_y < output_height; ++out_y)
+ {
+ const int in_y_origin = (out_y * stride_height) - pad_height;
+ for (int out_x = 0; out_x < output_width; ++out_x)
+ {
+ const int in_x_origin = (out_x * stride_width) - pad_width;
+ for (int out_channel = 0; out_channel < output_depth; ++out_channel)
+ {
+ int32_t acc = 0;
+ for (int filter_y = 0; filter_y < filter_height; ++filter_y)
+ {
+ const int in_y = in_y_origin + dilation_height_factor * filter_y;
+ for (int filter_x = 0; filter_x < filter_width; ++filter_x)
+ {
+ const int in_x = in_x_origin + dilation_width_factor * filter_x;
+
+ // Zero padding by omitting the areas outside the image.
+ const bool is_point_inside_image =
+ (in_x >= 0) && (in_x < input_width) && (in_y >= 0) && (in_y < input_height);
+
+ if (!is_point_inside_image)
+ {
+ continue;
+ }
+
+ for (int in_channel = 0; in_channel < input_depth; ++in_channel)
+ {
+ const int input_data_offset =
+ ((batch * input_height + in_y) * input_width + in_x) * input_depth + in_channel;
+
+ const int filter_data_offset =
+ ((out_channel * filter_height + filter_y) * filter_width + filter_x) *
+ input_depth +
+ in_channel;
+
+ const int32_t input_val = input_data[input_data_offset];
+ const int32_t filter_val = filter_data[filter_data_offset];
+ acc += (filter_val + filter_offset) * (input_val + input_offset);
+ }
+ }
+ }
+ if (bias_data)
+ {
+ acc += bias_data[out_channel];
+ }
+ acc = multiplyByQuantizedMultiplier(acc, output_multiplier, output_shift);
+ acc += output_offset;
+ acc = std::max(acc, output_activation_min);
+ acc = std::min(acc, output_activation_max);
+
+ const int output_data_offset =
+ ((batch * output_height + out_y) * output_width + out_x) * output_depth + out_channel;
+
+ output_data[output_data_offset] = static_cast<uint8_t>(acc);
+ }
+ }
+ }
+ }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_CONV2D_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALDiv.h b/onert-micro/luci-interpreter/pal/common/PALDiv.h
new file mode 100644
index 000000000..cca85cd22
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/PALDiv.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_DIV_COMMON_H
+#define LUCI_INTERPRETER_PAL_DIV_COMMON_H
+
+#include "Params.h"
+#include "PALUtils.h"
+#include "ProcessBroadcastShapes.h"
+
+namespace luci_interpreter_pal
+{
+template <typename T>
+inline void Div(const ArithmeticParams &params, const int flat_size, const T *input1_data,
+ const T *input2_data, T *output_data)
+{
+ T activation_min, activation_max;
+ getActivationParams(params, &activation_min, &activation_max);
+
+ for (int i = 0; i < flat_size; ++i)
+ output_data[i] =
+ std::min(std::max(input1_data[i] / input2_data[i], activation_min), activation_max);
+}
+
+template <typename T>
+inline void DivScalar(const ArithmeticParams &params, const int flat_size, const T *input_data,
+ const T scalar_value, T *output_data)
+{
+ T activation_min, activation_max;
+ getActivationParams(params, &activation_min, &activation_max);
+
+ for (int i = 0; i < flat_size; ++i)
+ output_data[i] =
+ std::min(std::max(input_data[i] / scalar_value, activation_min), activation_max);
+}
+
+template <typename T>
+inline void
+BroadcastDiv4DSlow(const ArithmeticParams &params,
+ const luci_interpreter::RuntimeShape &input1_shape, const T *input1_data,
+ const luci_interpreter::RuntimeShape &input2_shape, const T *input2_data,
+ const luci_interpreter::RuntimeShape &output_shape, T *output_data)
+{
+ const int flat_size = input1_shape.flatSize();
+
+ if (params.broadcast_category == BroadcastableOpCategory::kScalarFirstBroadcast)
+ {
+ return DivScalar(params, flat_size, input2_data, input1_data[0], output_data);
+ }
+ else if (params.broadcast_category == BroadcastableOpCategory::kScalarSecondBroadcast)
+ {
+ return DivScalar(params, flat_size, input1_data, input2_data[0], output_data);
+ }
+
+ NdArrayDesc<4> desc1;
+ NdArrayDesc<4> desc2;
+ NdArrayDescsForElementwiseBroadcast(input1_shape, input2_shape, &desc1, &desc2);
+ const luci_interpreter::RuntimeShape extended_output_shape =
+ luci_interpreter::RuntimeShape::extendedShape(4, output_shape);
+
+ T activation_min, activation_max;
+ getActivationParams(params, &activation_min, &activation_max);
+
+ // In Tensorflow, the dimensions are canonically named (batch_number, row,
+ // col, channel), with extents (batches, height, width, depth), with the
+ // trailing dimension changing most rapidly (channels has the smallest stride,
+ // typically 1 element).
+ //
+ // In generated C code, we store arrays with the dimensions reversed. The
+ // first dimension has smallest stride.
+ //
+ // We name our variables by their Tensorflow convention, but generate C code
+ // nesting loops such that the innermost loop has the smallest stride for the
+ // best cache behavior.
+ for (int b = 0; b < extended_output_shape.dims(0); ++b)
+ {
+ for (int y = 0; y < extended_output_shape.dims(1); ++y)
+ {
+ for (int x = 0; x < extended_output_shape.dims(2); ++x)
+ {
+ for (int c = 0; c < extended_output_shape.dims(3); ++c)
+ {
+ const int output_data_offset =
+ ((b * extended_output_shape.dims(1) + y) * extended_output_shape.dims(2) + x) *
+ extended_output_shape.dims(3) +
+ c;
+
+ output_data[output_data_offset] =
+ std::min(std::max(input1_data[subscriptToIndex(desc1, b, y, x, c)] /
+ input2_data[subscriptToIndex(desc2, b, y, x, c)],
+ activation_min),
+ activation_max);
+ }
+ }
+ }
+ }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_DIV_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALElu.h b/onert-micro/luci-interpreter/pal/common/PALElu.h
index fc8c573f8..661bd07ee 100644
--- a/onert-micro/luci-interpreter/pal/mcu/PALElu.h
+++ b/onert-micro/luci-interpreter/pal/common/PALElu.h
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2020 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,15 +18,20 @@
#ifndef LUCI_INTERPRETER_PAL_ELU_H
#define LUCI_INTERPRETER_PAL_ELU_H
-#include <tensorflow/lite/kernels/internal/reference/elu.h>
+#include "PALUtils.h"
+#include <cmath>
namespace luci_interpreter_pal
{
-static inline void Elu(const tflite::RuntimeShape &input_shape, const float *input_data,
- const tflite::RuntimeShape &output_shape, float *output_data)
+inline void Elu(const int flat_size, const float *input_data, float *output_data)
{
- tflite::reference_ops::Elu(input_shape, input_data, output_shape, output_data);
+ for (int i = 0; i < flat_size; i++)
+ {
+ float val = input_data[i];
+ float result = val < 0.0f ? std::expm1(val) : val;
+ output_data[i] = result;
+ }
}
} // namespace luci_interpreter_pal
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALNeg.h b/onert-micro/luci-interpreter/pal/common/PALExp.h
index b4e430ef8..5cf1ef6ed 100644
--- a/onert-micro/luci-interpreter/pal/cmsisnn/PALNeg.h
+++ b/onert-micro/luci-interpreter/pal/common/PALExp.h
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2020 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,19 +15,24 @@
* limitations under the License.
*/
-#ifndef LUCI_INTERPRETER_PAL_NEG_H
-#define LUCI_INTERPRETER_PAL_NEG_H
+#ifndef LUCI_INTERPRETER_PAL_EXP_H
+#define LUCI_INTERPRETER_PAL_EXP_H
-#include <tensorflow/lite/kernels/internal/reference/neg.h>
+#include "PALUtils.h"
namespace luci_interpreter_pal
{
-template <typename T>
-static inline void Negate(const tflite::RuntimeShape &input_shape, const T *input_data,
- const tflite::RuntimeShape &output_shape, T *output_data)
+
+inline void Exp(const int flat_size, const float *input_data, float *output_data)
{
- tflite::reference_ops::Negate(input_shape, input_data, output_shape, output_data);
+ for (int i = 0; i < flat_size; i++)
+ {
+ const float val = input_data[i];
+ const float result = std::exp(val);
+ output_data[i] = result;
+ }
}
+
} // namespace luci_interpreter_pal
-#endif // LUCI_INTERPRETER_PAL_NEG_H
+#endif // LUCI_INTERPRETER_PAL_EXP_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALFullyConnectedCommon.h b/onert-micro/luci-interpreter/pal/common/PALFullyConnectedCommon.h
new file mode 100644
index 000000000..14934cc72
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/PALFullyConnectedCommon.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2020 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_FULLY_CONNECTED_COMMON_H
+#define LUCI_INTERPRETER_PAL_FULLY_CONNECTED_COMMON_H
+
+#include "PALUtils.h"
+#include "Params.h"
+
+namespace luci_interpreter_pal
+{
+
+template <typename InputType, typename WeightType, typename OutputType, typename BiasType>
+inline void FullyConnected(const FullyConnectedParams &params, const int32_t *input_shape,
+ const InputType *input_data, const int32_t *filter_shape,
+ const WeightType *filter_data, const BiasType *bias_data,
+ const int32_t *output_shape, OutputType *output_data)
+{
+ const int32_t input_offset = params.input_offset;
+ const int32_t filter_offset = params.weights_offset;
+ const int32_t output_offset = params.output_offset;
+ const int32_t output_multiplier = params.output_multiplier;
+ const int output_shift = params.output_shift;
+ const int32_t output_activation_min = params.quantized_activation_min;
+ const int32_t output_activation_max = params.quantized_activation_max;
+
+ const int batches = input_shape[0];
+ const int output_depth = output_shape[1];
+ const int accum_depth = filter_shape[1];
+
+ for (int b = 0; b < batches; ++b)
+ {
+ for (int out_c = 0; out_c < output_depth; ++out_c)
+ {
+ BiasType acc = 0;
+ for (int d = 0; d < accum_depth; ++d)
+ {
+ int32_t input_val = input_data[b * accum_depth + d];
+ int32_t filter_val = filter_data[out_c * accum_depth + d];
+ acc += (filter_val + filter_offset) * (input_val + input_offset);
+ }
+ if (bias_data)
+ {
+ acc += bias_data[out_c];
+ }
+ int32_t acc_scaled = multiplyByQuantizedMultiplier(acc, output_multiplier, output_shift);
+ acc_scaled += output_offset;
+ acc_scaled = std::max(acc_scaled, output_activation_min);
+ acc_scaled = std::min(acc_scaled, output_activation_max);
+ output_data[out_c + output_depth * b] = static_cast<OutputType>(acc_scaled);
+ }
+ }
+}
+template <>
+inline void FullyConnected(const FullyConnectedParams &params, const int32_t *input_shape,
+ const float *input_data, const int32_t *filter_shape,
+ const float *filter_data, const float *bias_data,
+ const int32_t *output_shape, float *output_data)
+{
+ const float output_activation_min = params.float_activation_min;
+ const float output_activation_max = params.float_activation_max;
+
+ const int batches = input_shape[0];
+ const int output_depth = output_shape[1];
+ const int accum_depth = filter_shape[1];
+
+ for (int b = 0; b < batches; ++b)
+ {
+ for (int out_c = 0; out_c < output_depth; ++out_c)
+ {
+ float total = 0.f;
+ for (int d = 0; d < accum_depth; ++d)
+ {
+ total += input_data[b * accum_depth + d] * filter_data[out_c * accum_depth + d];
+ }
+ float bias_value = 0.0f;
+ if (bias_data)
+ {
+ bias_value = bias_data[out_c];
+ }
+ output_data[out_c + output_depth * b] =
+ std::min(std::max(total + bias_value, output_activation_min), output_activation_max);
+ }
+ }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_FULLY_CONNECTED_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALLogicalCommon.h b/onert-micro/luci-interpreter/pal/common/PALLogicalCommon.h
new file mode 100644
index 000000000..18173f583
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/PALLogicalCommon.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2020 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_LOGICAL_COMMON_H
+#define LUCI_INTERPRETER_PAL_LOGICAL_COMMON_H
+
+namespace luci_interpreter_pal
+{
+
+inline void LogicalCommon(const int flat_size, const bool *input1_data, const bool *input2_data,
+ bool *output_data, bool (*f)(bool, bool))
+{
+ for (int i = 0; i < flat_size; ++i)
+ {
+ output_data[i] = f(input1_data[i], input2_data[i]);
+ }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_LOGICAL_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALLogistic.h b/onert-micro/luci-interpreter/pal/common/PALLogistic.h
new file mode 100644
index 000000000..c0e3a3c18
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/PALLogistic.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2020 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_LOGISTIC_H
+#define LUCI_INTERPRETER_PAL_LOGISTIC_H
+
+#include "Params.h"
+#include "PALUtils.h"
+
+namespace luci_interpreter_pal
+{
+
+inline void Logistic(const int flat_size, const float *input_data, float *output_data)
+{
+ const float cutoff_upper = 16.619047164916992188f;
+ const float cutoff_lower = -9.f;
+
+ // Rational for using approximation in reference kernel.
+ // 0. This approximation gives enough precision for float.
+ // 1. This works around an issue on an embedded chipset where exp() does not
+ // return correctly as expected - exp(x) should return inf when overflown
+ // not 1.701417 IEEE 754 defines representation for inf.
+ // 2. This will speed up calculation and is matching the behavior in the
+ // optimized kernels. (check the definition of scalar_logistic_op<float>)
+
+ for (int i = 0; i < flat_size; i++)
+ {
+ float val = input_data[i];
+ float result;
+ if (val > cutoff_upper)
+ {
+ result = 1.0f;
+ }
+ else if (val < cutoff_lower)
+ {
+ result = std::exp(val);
+ }
+ else
+ {
+ result = 1.f / (1.f + std::exp(-val));
+ }
+ output_data[i] = result;
+ }
+}
+
+inline void Logistic(const int flat_size, const int8_t *input_data, float input_scale,
+ int input_zero_point, int8_t *output_data, float output_scale,
+ int output_zero_point)
+{
+ const float cutoff_upper = 16.619047164916992188f;
+ const float cutoff_lower = -9.f;
+
+ // Rational for using approximation in reference kernel.
+ // 0. This approximation gives enough precision for float.
+ // 1. This works around an issue on an embedded chipset where exp() does not
+ // return correctly as expected - exp(x) should return inf when overflown
+ // not 1.701417 IEEE 754 defines representation for inf.
+ // 2. This will speed up calculation and is matching the behavior in the
+ // optimized kernels. (check the definition of scalar_logistic_op<float>)
+
+ for (int i = 0; i < flat_size; i++)
+ {
+ // Dequantize.
+ float val = static_cast<float>((input_data[i] - input_zero_point) * input_scale);
+ float result;
+ if (val > cutoff_upper)
+ {
+ result = 1.0f;
+ }
+ else if (val < cutoff_lower)
+ {
+ result = std::exp(val);
+ }
+ else
+ {
+ result = 1.f / (1.f + std::exp(-val));
+ }
+ // Requantize
+ int8_t output = static_cast<int8_t>(result / output_scale + output_zero_point);
+ output_data[i] = output;
+ }
+}
+
+inline void Logistic(int32_t input_multiplier, int32_t input_left_shift, int32_t input_size,
+ const int16_t *ptr_input_data, int16_t *ptr_output_data)
+{
+ // We use the LUT for sigmoid and take into account, that
+ // tanh(x) = 2*sigmoid(2*x) - 1
+
+ // We scale by 3/4 to expand range [-8,8]->[-10.7,10.7].
+ // In case of general parameter scale, multiplier 3 is taken into account
+ // in TanhPrepare function and it is included in
+ // input_multiplier already.
+ if (input_multiplier == 0)
+ { // power of two case
+ input_multiplier = 3 << input_left_shift;
+ input_left_shift = 0;
+ }
+
+ int32_t round = (input_left_shift > 0) ? 1 << (input_left_shift - 1) : 0;
+
+ for (int i = 0; i < input_size; ++i, ptr_input_data++, ptr_output_data++)
+ {
+ int32_t input_data = ((*ptr_input_data) * input_multiplier + round) >> input_left_shift;
+
+ // We do interpolation on unsigned values.
+ uint32_t abs_input_data = abs(input_data);
+
+ // We divide by 2 power of 9, because
+ // we need to divide by 2 in power of 7 for
+ // the input conversion + 1/4 from the scale above.
+
+ // Define uh as uint32_t type not to make this function overflow.
+ uint32_t uh = abs_input_data >> 9;
+ uint32_t result;
+
+ if (uh >= 255)
+ {
+ // Saturate to maximum.
+ result = 0x7FFF << 10;
+ }
+ else
+ {
+ uint32_t ua = sigmoid_table_uint16[uh];
+ uint32_t ub = sigmoid_table_uint16[uh + 1];
+ uint32_t ut = abs_input_data & 0x1ff;
+ // Interpolation is done using the fractional bit.
+ result = (ua << 9) + ut * (ub - ua);
+ }
+
+ result = (input_data >= 0) ? (result + (1 << 9)) : ((1 << (16 + 9)) - result + (1 << 9) - 1);
+
+ // Back to 16-bit.
+ result >>= 10;
+
+ *ptr_output_data = result;
+ }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_LOGISTIC_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALMaxPool2DCommon.h b/onert-micro/luci-interpreter/pal/common/PALMaxPool2DCommon.h
new file mode 100644
index 000000000..034319b8a
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/PALMaxPool2DCommon.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2020 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_MAX_POOL_2D_COMMON_H
+#define LUCI_INTERPRETER_PAL_MAX_POOL_2D_COMMON_H
+
+#include "Params.h"
+#include "PALUtils.h"
+
+namespace luci_interpreter_pal
+{
+
+inline void MaxPool(const PoolParams &params, const luci_interpreter::RuntimeShape &input_shape,
+ const float *input_data, const luci_interpreter::RuntimeShape &output_shape,
+ float *output_data)
+{
+ const int batches = input_shape.dims(0);
+ const int depth = output_shape.dims(3);
+ const int input_height = input_shape.dims(1);
+ const int input_width = input_shape.dims(2);
+ const int output_height = output_shape.dims(1);
+ const int output_width = output_shape.dims(2);
+ const int stride_height = params.stride_height;
+ const int stride_width = params.stride_width;
+ for (int batch = 0; batch < batches; ++batch)
+ {
+ for (int out_y = 0; out_y < output_height; ++out_y)
+ {
+ for (int out_x = 0; out_x < output_width; ++out_x)
+ {
+ for (int channel = 0; channel < depth; ++channel)
+ {
+ const int in_x_origin = (out_x * stride_width) - params.padding_values.width;
+ const int in_y_origin = (out_y * stride_height) - params.padding_values.height;
+ // Compute the boundaries of the filter region clamped so as to
+ // ensure that the filter window fits in the input array.
+ const int filter_x_start = std::max(0, -in_x_origin);
+ const int filter_x_end = std::min(params.filter_width, input_width - in_x_origin);
+ const int filter_y_start = std::max(0, -in_y_origin);
+ const int filter_y_end = std::min(params.filter_height, input_height - in_y_origin);
+ float max = std::numeric_limits<float>::lowest();
+ for (int filter_y = filter_y_start; filter_y < filter_y_end; ++filter_y)
+ {
+ for (int filter_x = filter_x_start; filter_x < filter_x_end; ++filter_x)
+ {
+ const int in_x = in_x_origin + filter_x;
+ const int in_y = in_y_origin + filter_y;
+
+ const int input_data_offset =
+ ((batch * input_shape.dims(1) + in_y) * input_shape.dims(2) + in_x) *
+ input_shape.dims(3) +
+ channel;
+
+ max = std::max(max, input_data[input_data_offset]);
+ }
+ }
+ const int output_data_offset =
+ ((batch * output_shape.dims(1) + out_y) * output_shape.dims(2) + out_x) *
+ output_shape.dims(3) +
+ channel;
+
+ output_data[output_data_offset] =
+ std::min(std::max(max, params.float_activation_min), params.float_activation_max);
+ }
+ }
+ }
+ }
+}
+
+template <typename T>
+inline void MaxPool(const PoolParams &params, const luci_interpreter::RuntimeShape &input_shape,
+ const T *input_data, const luci_interpreter::RuntimeShape &output_shape,
+ T *output_data)
+{
+ const int batches = input_shape.dims(0);
+ const int depth = output_shape.dims(3);
+ const int input_height = input_shape.dims(1);
+ const int input_width = input_shape.dims(2);
+ const int output_height = output_shape.dims(1);
+ const int output_width = output_shape.dims(2);
+ const int stride_height = params.stride_height;
+ const int stride_width = params.stride_width;
+ for (int batch = 0; batch < batches; ++batch)
+ {
+ for (int out_y = 0; out_y < output_height; ++out_y)
+ {
+ for (int out_x = 0; out_x < output_width; ++out_x)
+ {
+ for (int channel = 0; channel < depth; ++channel)
+ {
+ const int in_x_origin = (out_x * stride_width) - params.padding_values.width;
+ const int in_y_origin = (out_y * stride_height) - params.padding_values.height;
+ // Compute the boundaries of the filter region clamped so as to
+ // ensure that the filter window fits in the input array.
+ const int filter_x_start = std::max(0, -in_x_origin);
+ const int filter_x_end = std::min(params.filter_width, input_width - in_x_origin);
+ const int filter_y_start = std::max(0, -in_y_origin);
+ const int filter_y_end = std::min(params.filter_height, input_height - in_y_origin);
+ T max = std::numeric_limits<T>::lowest();
+ for (int filter_y = filter_y_start; filter_y < filter_y_end; ++filter_y)
+ {
+ for (int filter_x = filter_x_start; filter_x < filter_x_end; ++filter_x)
+ {
+ const int in_x = in_x_origin + filter_x;
+ const int in_y = in_y_origin + filter_y;
+
+ const int input_data_offset =
+ ((batch * input_shape.dims(1) + in_y) * input_shape.dims(2) + in_x) *
+ input_shape.dims(3) +
+ channel;
+
+ max = std::max(max, input_data[input_data_offset]);
+ }
+ }
+ max = std::max<T>(max, params.quantized_activation_min);
+ max = std::min<T>(max, params.quantized_activation_max);
+
+ const int output_data_offset =
+ ((batch * output_shape.dims(1) + out_y) * output_shape.dims(2) + out_x) *
+ output_shape.dims(3) +
+ channel;
+
+ output_data[output_data_offset] = static_cast<T>(max);
+ }
+ }
+ }
+ }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_MAX_POOL_2D_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALMulCommon.h b/onert-micro/luci-interpreter/pal/common/PALMulCommon.h
new file mode 100644
index 000000000..f17104030
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/PALMulCommon.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_MUL_COMMON_H
+#define LUCI_INTERPRETER_PAL_MUL_COMMON_H
+
+#include "Params.h"
+#include "PALUtils.h"
+#include "ProcessBroadcastShapes.h"
+
+namespace luci_interpreter_pal
+{
+template <typename T>
+inline void Mul(const ArithmeticParams &params, const int flat_size, const T *input1_data,
+ const T *input2_data, T *output_data)
+{
+ T activation_min, activation_max;
+ getActivationParams(params, &activation_min, &activation_max);
+
+ for (int i = 0; i < flat_size; ++i)
+ output_data[i] =
+ std::min(std::max(input1_data[i] * input2_data[i], activation_min), activation_max);
+}
+
+template <typename T>
+inline void MulScalar(const ArithmeticParams &params, const int flat_size, const T *input_data,
+ const T scalar_value, T *output_data)
+{
+ T activation_min, activation_max;
+ getActivationParams(params, &activation_min, &activation_max);
+
+ for (int i = 0; i < flat_size; ++i)
+ output_data[i] =
+ std::min(std::max(input_data[i] * scalar_value, activation_min), activation_max);
+}
+
+template <typename T>
+inline void
+BroadcastMul4DSlow(const ArithmeticParams &params,
+ const luci_interpreter::RuntimeShape &input1_shape, const T *input1_data,
+ const luci_interpreter::RuntimeShape &input2_shape, const T *input2_data,
+ const luci_interpreter::RuntimeShape &output_shape, T *output_data)
+{
+ const int flat_size = input1_shape.flatSize();
+
+ if (params.broadcast_category == BroadcastableOpCategory::kScalarFirstBroadcast)
+ {
+ return MulScalar(params, flat_size, input2_data, input1_data[0], output_data);
+ }
+ else if (params.broadcast_category == BroadcastableOpCategory::kScalarSecondBroadcast)
+ {
+ return MulScalar(params, flat_size, input1_data, input2_data[0], output_data);
+ }
+
+ NdArrayDesc<4> desc1;
+ NdArrayDesc<4> desc2;
+ NdArrayDescsForElementwiseBroadcast(input1_shape, input2_shape, &desc1, &desc2);
+ const luci_interpreter::RuntimeShape extended_output_shape =
+ luci_interpreter::RuntimeShape::extendedShape(4, output_shape);
+
+ T activation_min, activation_max;
+ getActivationParams(params, &activation_min, &activation_max);
+
+ // In Tensorflow, the dimensions are canonically named (batch_number, row,
+ // col, channel), with extents (batches, height, width, depth), with the
+ // trailing dimension changing most rapidly (channels has the smallest stride,
+ // typically 1 element).
+ //
+ // In generated C code, we store arrays with the dimensions reversed. The
+ // first dimension has smallest stride.
+ //
+ // We name our variables by their Tensorflow convention, but generate C code
+ // nesting loops such that the innermost loop has the smallest stride for the
+ // best cache behavior.
+ for (int b = 0; b < extended_output_shape.dims(0); ++b)
+ {
+ for (int y = 0; y < extended_output_shape.dims(1); ++y)
+ {
+ for (int x = 0; x < extended_output_shape.dims(2); ++x)
+ {
+ for (int c = 0; c < extended_output_shape.dims(3); ++c)
+ {
+ const int output_data_offset =
+ ((b * extended_output_shape.dims(1) + y) * extended_output_shape.dims(2) + x) *
+ extended_output_shape.dims(3) +
+ c;
+
+ output_data[output_data_offset] =
+ std::min(std::max(input1_data[subscriptToIndex(desc1, b, y, x, c)] *
+ input2_data[subscriptToIndex(desc2, b, y, x, c)],
+ activation_min),
+ activation_max);
+ }
+ }
+ }
+ }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_MUL_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALNeg.h b/onert-micro/luci-interpreter/pal/common/PALNeg.h
index c88b04582..4c9153886 100644
--- a/onert-micro/luci-interpreter/pal/linux/PALNeg.h
+++ b/onert-micro/luci-interpreter/pal/common/PALNeg.h
@@ -1,6 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,15 +17,29 @@
#ifndef LUCI_INTERPRETER_PAL_NEG_H
#define LUCI_INTERPRETER_PAL_NEG_H
-#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
-
namespace luci_interpreter_pal
{
template <typename T>
-static inline void Negate(const tflite::RuntimeShape &input_shape, const T *input_data,
- const tflite::RuntimeShape &output_shape, T *output_data)
+inline void Negate(const luci_interpreter::RuntimeShape &input_shape, const T *input_data,
+ const luci_interpreter::RuntimeShape &output_shape, T *output_data)
+
{
- tflite::reference_ops::Negate(input_shape, input_data, output_shape, output_data);
+ // check that input and output dimensions are equal
+ int N = input_shape.dimensionsCount();
+ assert(N == output_shape.dimensionsCount());
+
+ // check that sizes of all dimensions are equal
+ for (int i = 0; i < N; ++i)
+ {
+ assert(input_shape.dims(i) == output_shape.dims(i));
+ }
+
+ const int flat_size = input_shape.flatSize();
+
+ for (int i = 0; i < flat_size; ++i)
+ {
+ output_data[i] = -input_data[i];
+ }
}
} // namespace luci_interpreter_pal
diff --git a/onert-micro/luci-interpreter/pal/common/PALPad.h b/onert-micro/luci-interpreter/pal/common/PALPad.h
new file mode 100644
index 000000000..f9dd73f1b
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/PALPad.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_PAD_H
+#define LUCI_INTERPRETER_PAL_PAD_H
+
+#include "PALUtils.h"
+
+namespace luci_interpreter_pal
+{
+
+constexpr int PadKernelMaxDimensionCount() { return 5; }
+
+void Pad(const PadParams &op_params, const luci_interpreter::RuntimeShape &input_shape,
+ const float *input_data, const float *pad_value_ptr,
+ const luci_interpreter::RuntimeShape &output_shape, float *output_data)
+{
+ // Runtime calls are currently fixed at 5 dimensions. Copy inputs so we can
+ // pad them to 5 dims (yes, we are "padding the padding").
+ int left_padding_copy[PadKernelMaxDimensionCount()];
+ for (int i = 0; i < PadKernelMaxDimensionCount(); i++)
+ {
+ left_padding_copy[i] = 0;
+ }
+ for (int i = 0; i < op_params.left_padding_count; ++i)
+ {
+ left_padding_copy[i + PadKernelMaxDimensionCount() - op_params.left_padding_count] =
+ op_params.left_padding[i];
+ }
+ int right_padding_copy[PadKernelMaxDimensionCount()];
+ for (int i = 0; i < PadKernelMaxDimensionCount(); i++)
+ {
+ right_padding_copy[i] = 0;
+ }
+ for (int i = 0; i < op_params.right_padding_count; ++i)
+ {
+ right_padding_copy[i + PadKernelMaxDimensionCount() - op_params.right_padding_count] =
+ op_params.right_padding[i];
+ }
+ const auto extended_output =
+ luci_interpreter::RuntimeShape::extendedShape(PadKernelMaxDimensionCount(), output_shape);
+ const int output_batch = extended_output.dims(0);
+ const int output_plane = extended_output.dims(1);
+ const int output_height = extended_output.dims(2);
+ const int output_width = extended_output.dims(3);
+ const int output_depth = extended_output.dims(4);
+
+ const int left_b_padding = left_padding_copy[0];
+ const int left_p_padding = left_padding_copy[1];
+ const int left_h_padding = left_padding_copy[2];
+ const int left_w_padding = left_padding_copy[3];
+ const int left_d_padding = left_padding_copy[4];
+
+ const int right_b_padding = right_padding_copy[0];
+ const int right_p_padding = right_padding_copy[1];
+ const int right_h_padding = right_padding_copy[2];
+ const int right_w_padding = right_padding_copy[3];
+ const int right_d_padding = right_padding_copy[4];
+
+ const float pad_value = *pad_value_ptr;
+
+ const float *in_ptr = input_data;
+ float *out_ptr = output_data;
+ for (int out_b = 0; out_b < output_batch; ++out_b)
+ {
+ for (int out_p = 0; out_p < output_plane; ++out_p)
+ {
+ for (int out_h = 0; out_h < output_height; ++out_h)
+ {
+ for (int out_w = 0; out_w < output_width; ++out_w)
+ {
+ for (int out_d = 0; out_d < output_depth; ++out_d)
+ {
+ if (out_b < left_b_padding || out_b >= output_batch - right_b_padding ||
+ out_p < left_p_padding || out_p >= output_plane - right_p_padding ||
+ out_h < left_h_padding || out_h >= output_height - right_h_padding ||
+ out_w < left_w_padding || out_w >= output_width - right_w_padding ||
+ out_d < left_d_padding || out_d >= output_depth - right_d_padding)
+ {
+ *out_ptr++ = pad_value;
+ }
+ else
+ {
+ *out_ptr++ = *in_ptr++;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_PAD_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALReduceCommon.h b/onert-micro/luci-interpreter/pal/common/PALReduceCommon.h
new file mode 100644
index 000000000..a5b0e10dd
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/PALReduceCommon.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2020 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_TANH_H
+#define LUCI_INTERPRETER_PAL_TANH_H
+
+#include "PALUtils.h"
+
+namespace luci_interpreter_pal
+{
+namespace
+{
+// This method parses the input 'axis' to remove duplicates and handle negative
+// values, and returns a valid 'out_axis'
+inline bool resolveAxis(const int num_dims, const int *axis, const int64_t num_axis,
+ int *out_num_axis)
+{
+ int out_axis[2];
+ *out_num_axis = 0; // Just in case.
+ // Short-circuit axis resolution for scalars; the axis will go unused.
+ if (num_dims == 0)
+ {
+ return true;
+ }
+ // o(n^2) is fine since out_num_axis should be really small, mostly <= 4
+ for (int64_t idx = 0; idx < num_axis; ++idx)
+ {
+ // Handle negative index. A positive index 'p_idx' can be represented as a
+ // negative index 'n_idx' as: n_idx = p_idx-num_dims
+ // eg: For num_dims=3, [0, 1, 2] is the same as [-3, -2, -1] */
+ int current = axis[idx] < 0 ? (axis[idx] + num_dims) : axis[idx];
+ if (current < 0 || current >= num_dims)
+ {
+ return false;
+ }
+ bool is_dup = false;
+ for (int j = 0; j < *out_num_axis; ++j)
+ {
+ if (out_axis[j] == current)
+ {
+ is_dup = true;
+ break;
+ }
+ }
+ if (!is_dup)
+ {
+ out_axis[*out_num_axis] = current;
+ *out_num_axis += 1;
+ }
+ }
+ return true;
+}
+
+} // namespace
+
+// Computes the generic value (i.e., sum/max/min/prod) of elements across
+// dimensions given in axis. It needs to pass in init_value and reducer.
+template <typename T>
+inline void ReduceGeneric(const T *input_data, const int *input_dims, const int input_num_dims,
+ T *output_data, const int *axis, const int64_t num_axis_dimensions,
+ T init_value, const int output_flat_size, T reducer(const T, const T))
+{
+ // Return early when input shape has zero dim.
+ for (int i = 0; i < input_num_dims; ++i)
+ {
+ if (input_dims[i] == 0)
+ return;
+ }
+
+ for (size_t idx = 0; idx < output_flat_size; ++idx)
+ {
+ output_data[idx] = init_value;
+ }
+
+ // Resolve axis.
+ int num_resolved_axis = 0;
+ if (!resolveAxis(input_num_dims, axis, num_axis_dimensions, &num_resolved_axis))
+ {
+ return;
+ }
+
+ int temp_index[5];
+ // Reset input iterator.
+ for (int idx = 0; idx < input_num_dims; ++idx)
+ {
+ temp_index[idx] = 0;
+ }
+ // Iterate through input_data.
+ do
+ {
+ size_t input_offset = reducedOutputOffset(input_num_dims, input_dims, temp_index, 0, nullptr);
+ size_t output_offset =
+ reducedOutputOffset(input_num_dims, input_dims, temp_index, num_resolved_axis, axis);
+ output_data[output_offset] = reducer(output_data[output_offset], input_data[input_offset]);
+ } while (nextIndex(input_num_dims, input_dims, temp_index));
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_TANH_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALReluCommon.h b/onert-micro/luci-interpreter/pal/common/PALReluCommon.h
new file mode 100644
index 000000000..260586ab3
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/PALReluCommon.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2020 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_RELU_COMMON_H
+#define LUCI_INTERPRETER_PAL_RELU_COMMON_H
+
+#include "PALUtils.h"
+
+namespace luci_interpreter_pal
+{
+
+inline void ReLUCommon(const int flat_size, const float *input_data, float *output_data,
+ const float alpha, const bool is_relu_6)
+{
+ const float relu_6_value = 6.0f;
+ for (int i = 0; i < flat_size; i++)
+ {
+ const float val = input_data[i];
+ float result = val > 0 ? val : val * alpha;
+ result = is_relu_6 ? (result > relu_6_value ? relu_6_value : result) : result;
+ output_data[i] = result;
+ }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_RELU_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALResizeBilinear.h b/onert-micro/luci-interpreter/pal/common/PALResizeBilinear.h
new file mode 100644
index 000000000..19686b702
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/PALResizeBilinear.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_RESIZEBILINEAR_COMMON_H
+#define LUCI_INTERPRETER_PAL_RESIZEBILINEAR_COMMON_H
+
+#include "PALUtils.h"
+
+namespace luci_interpreter_pal
+{
+
+// Offset function for positining corresponding index in input data
+// int i0 - batches, int i1 - height, int i2 - width, int i3 - depth
+inline int Offset(const luci_interpreter::RuntimeShape &shape, int i0, int i1, int i2, int i3)
+{
+ assert(shape.dimensionsCount() == 4);
+
+ const int32_t *dims_data = reinterpret_cast<const int32_t *>(shape.dimsData());
+ LUCI_INTERPRETER_CHECK(i0 >= 0 && i0 < dims_data[0]);
+ LUCI_INTERPRETER_CHECK(i1 >= 0 && i1 < dims_data[1]);
+ LUCI_INTERPRETER_CHECK(i2 >= 0 && i2 < dims_data[2]);
+ LUCI_INTERPRETER_CHECK(i3 >= 0 && i3 < dims_data[3]);
+ return ((i0 * dims_data[1] + i1) * dims_data[2] + i2) * dims_data[3] + i3;
+}
+
+inline void ComputeInterpolationValues(const float value, const float scale,
+ const bool half_pixel_centers, int32_t input_size,
+ float *scaled_value, int32_t *lower_bound,
+ int32_t *upper_bound)
+{
+ if (half_pixel_centers)
+ {
+ *scaled_value = (value + 0.5f) * scale - 0.5f;
+ }
+ else
+ {
+ *scaled_value = value * scale;
+ }
+ float scaled_value_floor = std::floor(*scaled_value);
+ *lower_bound = std::max(static_cast<int32_t>(scaled_value_floor), static_cast<int32_t>(0));
+ *upper_bound = std::min(static_cast<int32_t>(std::ceil(*scaled_value)), input_size - 1);
+}
+
+template <typename T>
+static inline void
+ResizeBilinear(const circle::ResizeBilinearOptions *op_params,
+ const luci_interpreter::RuntimeShape &unextended_input_shape, const T *input_data,
+ const luci_interpreter::RuntimeShape &unextended_output_size_shape,
+ const int32_t *output_size_data,
+ const luci_interpreter::RuntimeShape &unextended_output_shape, T *output_data)
+{
+ // If half_pixel_centers is True, align_corners must be False.
+ LUCI_INTERPRETER_CHECK(!op_params->half_pixel_centers() || !op_params->align_corners());
+
+ assert(unextended_input_shape.dimensionsCount() >= 4);
+ assert(unextended_output_size_shape.dimensionsCount() >= 1);
+ assert(unextended_output_shape.dimensionsCount() >= 4);
+ const luci_interpreter::RuntimeShape input_shape =
+ luci_interpreter::RuntimeShape::extendedShape(4, unextended_input_shape);
+ const luci_interpreter::RuntimeShape output_size_shape =
+ luci_interpreter::RuntimeShape::extendedShape(4, unextended_output_size_shape);
+ const luci_interpreter::RuntimeShape output_shape =
+ luci_interpreter::RuntimeShape::extendedShape(4, unextended_output_shape);
+
+ int32_t batches = MatchingDim(input_shape, 0, output_shape, 0);
+ int32_t input_height = input_shape.dims(1);
+ int32_t input_width = input_shape.dims(2);
+ int32_t depth = MatchingDim(input_shape, 3, output_shape, 3);
+
+ assert(output_size_shape.dims(0) == 1);
+ assert(output_size_shape.dims(1) == 1);
+ assert(output_size_shape.dims(2) == 1);
+ assert(output_size_shape.dims(3) == 2);
+
+ int32_t output_height = output_size_data[Offset(output_size_shape, 0, 0, 0, 0)];
+ int32_t output_width = output_size_data[Offset(output_size_shape, 0, 0, 0, 1)];
+
+ float height_scale = static_cast<float>(input_height) / output_height;
+ float width_scale = static_cast<float>(input_width) / output_width;
+ if (op_params->align_corners() && output_height > 1)
+ {
+ height_scale = static_cast<float>(input_height - 1) / (output_height - 1);
+ }
+ if (op_params->align_corners() && output_width > 1)
+ {
+ width_scale = static_cast<float>(input_width - 1) / (output_width - 1);
+ }
+ const float rounding_offset = std::numeric_limits<T>::is_integer ? .5f : .0f;
+
+ for (int b = 0; b < batches; ++b)
+ {
+ for (int y = 0; y < output_height; ++y)
+ {
+ float input_y;
+ int32_t y0, y1;
+ ComputeInterpolationValues(y, height_scale, op_params->half_pixel_centers(), input_height,
+ &input_y, &y0, &y1);
+ for (int x = 0; x < output_width; ++x)
+ {
+ float input_x;
+ int32_t x0, x1;
+ ComputeInterpolationValues(x, width_scale, op_params->half_pixel_centers(), input_width,
+ &input_x, &x0, &x1);
+ for (int c = 0; c < depth; ++c)
+ {
+ T interpolation = static_cast<T>(
+ input_data[Offset(input_shape, b, y0, x0, c)] * (1 - (input_y - y0)) *
+ (1 - (input_x - x0)) +
+ input_data[Offset(input_shape, b, y1, x0, c)] * (input_y - y0) * (1 - (input_x - x0)) +
+ input_data[Offset(input_shape, b, y0, x1, c)] * (1 - (input_y - y0)) * (input_x - x0) +
+ input_data[Offset(input_shape, b, y1, x1, c)] * (input_y - y0) * (input_x - x0) +
+ rounding_offset);
+ output_data[Offset(output_shape, b, y, x, c)] = interpolation;
+ }
+ }
+ }
+ }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_RESIZEBILINEAR_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALSoftmax.h b/onert-micro/luci-interpreter/pal/common/PALSoftmax.h
new file mode 100644
index 000000000..a67785675
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/PALSoftmax.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_SOFTMAX_COMMON_H
+#define LUCI_INTERPRETER_PAL_SOFTMAX_COMMON_H
+
+namespace luci_interpreter_pal
+{
+namespace
+{
+
+inline int flatSizeSkipDim(const luci_interpreter::RuntimeShape &shape, int skip_dim)
+{
+ const int dims_count = shape.dimensionsCount();
+ const auto *dims_data = shape.dimsData();
+ int flat_size = 1;
+ for (int i = 0; i < dims_count; ++i)
+ {
+ flat_size *= (i == skip_dim) ? 1 : dims_data[i];
+ }
+ return flat_size;
+}
+
+} // namespace
+
+inline void Softmax(const double beta, const luci_interpreter::RuntimeShape &input_shape,
+ const float *input_data, float *output_data)
+{
+ const int trailing_dim = input_shape.dimensionsCount() - 1;
+ const int outer_size = flatSizeSkipDim(input_shape, trailing_dim);
+
+ const int depth = input_shape.dims(trailing_dim);
+
+ for (int i = 0; i < outer_size; ++i)
+ {
+ // Find max element value which we'll use to ensure numerical stability
+ // taking advantage of the following equality:
+ // exp(x[i])/sum(exp(x[i])) == exp(x[i]+C)/sum(exp(x[i]+C))
+ float max = std::numeric_limits<float>::lowest();
+ for (int c = 0; c < depth; ++c)
+ {
+ max = std::max(max, input_data[i * depth + c]);
+ }
+
+ // Compute sum.
+ float sum = 0.f;
+ for (int c = 0; c < depth; ++c)
+ {
+ const float exp_c = std::exp((input_data[i * depth + c] - max) * static_cast<float>(beta));
+ output_data[i * depth + c] = exp_c;
+ sum += exp_c;
+ }
+
+ // Compute result.
+ for (int c = 0; c < depth; ++c)
+ {
+ output_data[i * depth + c] = output_data[i * depth + c] / sum;
+ }
+ }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_SOFTMAX_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALStridedSlice.h b/onert-micro/luci-interpreter/pal/common/PALStridedSlice.h
new file mode 100644
index 000000000..15b3209c1
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/PALStridedSlice.h
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2020 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_STRIDED_SLICE_H
+#define LUCI_INTERPRETER_PAL_STRIDED_SLICE_H
+
+#include "Params.h"
+
+namespace luci_interpreter_pal
+{
+
+namespace
+{
+// Use until std::clamp() is available from C++17.
+inline int clamp(const int v, const int lo, const int hi)
+{
+ if (hi < v)
+ return hi;
+ if (v < lo)
+ return lo;
+ return v;
+}
+
+inline bool loopCondition(int index, int stop, int stride)
+{
+ // True when we have reached the end of an axis and should loop.
+ return stride > 0 ? index >= stop : index <= stop;
+}
+
+// Return the "real" index for the end of iteration along that axis. This is an
+// "end" in the traditional C sense, in that it points to one past the last
+// element. ie. So if you were iterating through all elements of a 1D array of
+// size 4, this function would return 4 as the stop, because it is one past the
+// "real" indices of 0, 1, 2 & 3.
+inline int stopForAxis(const StridedSliceParams &params,
+ const luci_interpreter::RuntimeShape &input_shape, int axis,
+ int start_for_axis)
+{
+ const auto end_mask = params.end_mask;
+ const auto shrink_axis_mask = params.shrink_axis_mask;
+ const auto *stop_indices = params.stop_indices;
+ const auto *strides = params.strides;
+ const int axis_size = input_shape.dims(axis);
+ if (axis_size == 0)
+ {
+ return 0;
+ }
+
+ // Begin with the specified index
+ const bool shrink_axis = shrink_axis_mask & (1 << axis);
+ int stop = stop_indices[axis];
+
+ // When shrinking an axis, the end position does not matter (and can be
+ // incorrect when negative indexing is used, see Issue #19260). Always use
+ // start_for_axis + 1 to generate a length 1 slice, since start_for_axis has
+ // already been adjusted for negative indices.
+ if (shrink_axis)
+ {
+ return start_for_axis + 1;
+ }
+
+ // end_mask override
+ if (end_mask & (1 << axis))
+ {
+ if (strides[axis] > 0)
+ {
+ // Forward iteration - use the last element. These values will get
+ // clamped below
+ stop = std::numeric_limits<int>::max();
+ }
+ else
+ {
+ // Backward iteration - use the first element.
+ stop = std::numeric_limits<int>::lowest();
+ }
+ }
+
+ // Handle negative indices
+ if (stop < 0)
+ {
+ stop += axis_size;
+ }
+
+ // Clamping
+ // Because the end index points one past the last element, we need slightly
+ // different clamping ranges depending on the direction.
+ if (strides[axis] > 0)
+ {
+ // Forward iteration
+ stop = clamp(stop, 0, axis_size);
+ }
+ else
+ {
+ // Backward iteration
+ stop = clamp(stop, -1, axis_size - 1);
+ }
+
+ return stop;
+}
+
+// Return the index for the first element along that axis. This index will be a
+// positive integer between [0, axis_size] (or [-1, axis_size -1] if stride < 0)
+// that can be used to index directly into the data.
+inline int startForAxis(const StridedSliceParams &params,
+ const luci_interpreter::RuntimeShape &input_shape, int axis)
+{
+ const auto begin_mask = params.begin_mask;
+ const auto *start_indices = params.start_indices;
+ const auto *strides = params.strides;
+ const int axis_size = input_shape.dims(axis);
+ if (axis_size == 0)
+ {
+ return 0;
+ }
+ // Begin with the specified index.
+ int start = start_indices[axis];
+
+ // begin_mask override
+ if (begin_mask & 1 << axis)
+ {
+ if (strides[axis] > 0)
+ {
+ // Forward iteration - use the first element. These values will get
+ // clamped below (Note: We could have set them to 0 and axis_size-1, but
+ // use lowest() and max() to maintain symmetry with StopForAxis())
+ start = std::numeric_limits<int>::lowest();
+ }
+ else
+ {
+ // Backward iteration - use the last element.
+ start = std::numeric_limits<int>::max();
+ }
+ }
+
+ // Handle negative indices
+ if (start < 0)
+ {
+ start += axis_size;
+ }
+
+ // Clamping
+ if (strides[axis] > 0)
+ {
+ // Forward iteration
+ start = clamp(start, 0, axis_size);
+ }
+ else
+ {
+ // Backward iteration
+ start = clamp(start, -1, axis_size - 1);
+ }
+
+ return start;
+}
+
+inline void stridedSlicePadIndices(StridedSliceParams *p, int dim_count)
+{
+ const int pad_count = dim_count - p->start_indices_count;
+
+ // Pad indices at start, so move arrays by pad_count.
+ for (int i = p->start_indices_count - 1; i >= 0; --i)
+ {
+ p->strides[i + pad_count] = p->strides[i];
+ p->start_indices[i + pad_count] = p->start_indices[i];
+ p->stop_indices[i + pad_count] = p->stop_indices[i];
+ }
+ for (int i = 0; i < pad_count; ++i)
+ {
+ p->start_indices[i] = 0;
+ p->stop_indices[i] = 1;
+ p->strides[i] = 1;
+ }
+
+ // Pad masks with 0s or 1s as required.
+ p->shrink_axis_mask <<= pad_count;
+ p->ellipsis_mask <<= pad_count;
+ p->new_axis_mask <<= pad_count;
+ p->begin_mask <<= pad_count;
+ p->end_mask <<= pad_count;
+ p->begin_mask |= (1 << pad_count) - 1;
+ p->end_mask |= (1 << pad_count) - 1;
+
+ p->start_indices_count = dim_count;
+ p->stop_indices_count = dim_count;
+ p->strides_count = dim_count;
+}
+
+} // namespace
+
+template <typename T>
+inline void StridedSlice(StridedSliceParams &op_params,
+ const luci_interpreter::RuntimeShape &unextended_input_shape,
+ const T *input_data, T *output_data)
+{
+ const luci_interpreter::RuntimeShape input_shape =
+ luci_interpreter::RuntimeShape::extendedShape(5, unextended_input_shape);
+
+ // Reverse and pad to 5 dimensions because that is what the runtime code
+ // requires (ie. all shapes must be 5D and are given backwards).
+ stridedSlicePadIndices(&op_params, 5);
+
+ const int start_0 = startForAxis(op_params, input_shape, 0);
+ const int stop_0 = stopForAxis(op_params, input_shape, 0, start_0);
+ const int start_1 = startForAxis(op_params, input_shape, 1);
+ const int stop_1 = stopForAxis(op_params, input_shape, 1, start_1);
+ const int start_2 = startForAxis(op_params, input_shape, 2);
+ const int stop_2 = stopForAxis(op_params, input_shape, 2, start_2);
+ const int start_3 = startForAxis(op_params, input_shape, 3);
+ const int stop_3 = stopForAxis(op_params, input_shape, 3, start_3);
+ const int start_4 = startForAxis(op_params, input_shape, 4);
+ const int stop_4 = stopForAxis(op_params, input_shape, 4, start_4);
+
+ for (int offset_0 = start_0 * input_shape.dims(1), end_0 = stop_0 * input_shape.dims(1),
+ step_0 = op_params.strides[0] * input_shape.dims(1);
+ !loopCondition(offset_0, end_0, op_params.strides[0]); offset_0 += step_0)
+ {
+ for (int offset_1 = (offset_0 + start_1) * input_shape.dims(2),
+ end_1 = (offset_0 + stop_1) * input_shape.dims(2),
+ step_1 = op_params.strides[1] * input_shape.dims(2);
+ !loopCondition(offset_1, end_1, op_params.strides[1]); offset_1 += step_1)
+ {
+ for (int offset_2 = (offset_1 + start_2) * input_shape.dims(3),
+ end_2 = (offset_1 + stop_2) * input_shape.dims(3),
+ step_2 = op_params.strides[2] * input_shape.dims(3);
+ !loopCondition(offset_2, end_2, op_params.strides[2]); offset_2 += step_2)
+ {
+ for (int offset_3 = (offset_2 + start_3) * input_shape.dims(4),
+ end_3 = (offset_2 + stop_3) * input_shape.dims(4),
+ step_3 = op_params.strides[3] * input_shape.dims(4);
+ !loopCondition(offset_3, end_3, op_params.strides[3]); offset_3 += step_3)
+ {
+ for (int offset_4 = offset_3 + start_4, end_4 = offset_3 + stop_4;
+ !loopCondition(offset_4, end_4, op_params.strides[4]);
+ offset_4 += op_params.strides[4])
+ {
+ *output_data++ = input_data[offset_4];
+ }
+ }
+ }
+ }
+ }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_STRIDED_SLICE_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALSub.h b/onert-micro/luci-interpreter/pal/common/PALSub.h
new file mode 100644
index 000000000..faa94fdd3
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/PALSub.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_SUB_COMMON_H
+#define LUCI_INTERPRETER_PAL_SUB_COMMON_H
+
+#include "PALUtils.h"
+
+namespace luci_interpreter_pal
+{
+template <typename T>
+static inline void Sub(const ArithmeticParams &params, const int flat_size, const T *input1_data,
+ const T *input2_data, T *output_data)
+{
+ T activation_min, activation_max;
+ getActivationParams(params, &activation_min, &activation_max);
+
+ for (int i = 0; i < flat_size; ++i)
+ output_data[i] =
+ std::min(std::max(input1_data[i] - input2_data[i], activation_min), activation_max);
+}
+
+template <typename T>
+inline void
+BroadcastSub4DSlow(const ArithmeticParams &params,
+ const luci_interpreter::RuntimeShape &input1_shape, const T *input1_data,
+ const luci_interpreter::RuntimeShape &input2_shape, const T *input2_data,
+ const luci_interpreter::RuntimeShape &output_shape, T *output_data)
+{
+ NdArrayDesc<4> desc1;
+ NdArrayDesc<4> desc2;
+ NdArrayDescsForElementwiseBroadcast(input1_shape, input2_shape, &desc1, &desc2);
+ const luci_interpreter::RuntimeShape extended_output_shape =
+ luci_interpreter::RuntimeShape::extendedShape(4, output_shape);
+
+ T activation_min, activation_max;
+ getActivationParams(params, &activation_min, &activation_max);
+
+ // In Tensorflow, the dimensions are canonically named (batch_number, row,
+ // col, channel), with extents (batches, height, width, depth), with the
+ // trailing dimension changing most rapidly (channels has the smallest stride,
+ // typically 1 element).
+ //
+ // In generated C code, we store arrays with the dimensions reversed. The
+ // first dimension has smallest stride.
+ //
+ // We name our variables by their Tensorflow convention, but generate C code
+ // nesting loops such that the innermost loop has the smallest stride for the
+ // best cache behavior.
+ for (int b = 0; b < extended_output_shape.dims(0); ++b)
+ {
+ for (int y = 0; y < extended_output_shape.dims(1); ++y)
+ {
+ for (int x = 0; x < extended_output_shape.dims(2); ++x)
+ {
+ for (int c = 0; c < extended_output_shape.dims(3); ++c)
+ {
+ const int output_data_offset =
+ ((b * extended_output_shape.dims(1) + y) * extended_output_shape.dims(2) + x) *
+ extended_output_shape.dims(3) +
+ c;
+
+ output_data[output_data_offset] =
+ std::min(std::max(input1_data[subscriptToIndex(desc1, b, y, x, c)] -
+ input2_data[subscriptToIndex(desc2, b, y, x, c)],
+ activation_min),
+ activation_max);
+ }
+ }
+ }
+ }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_SUB_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALTanh.h b/onert-micro/luci-interpreter/pal/common/PALTanh.h
new file mode 100644
index 000000000..506657ebe
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/PALTanh.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2020 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_TANH_H
+#define LUCI_INTERPRETER_PAL_TANH_H
+
+#include "PALUtils.h"
+
+namespace luci_interpreter_pal
+{
+
+inline void Tanh(const int flat_size, const float *input_data, float *output_data)
+{
+ for (int i = 0; i < flat_size; i++)
+ {
+ float val = input_data[i];
+ float result = std::tanh(val);
+ output_data[i] = result;
+ }
+}
+
+inline void Tanh(int32_t input_multiplier, int32_t input_left_shift, const int flat_size,
+ const int16_t *ptr_input_data, int16_t *ptr_output_data)
+{
+ // We use the LUT for sigmoid and take into account, that
+ // tanh(x) = 2*sigmoid(2*x) - 1
+
+ // We scale by 3/4 to expand range [-8,8]->[-10.7,10.7].
+ // In case of general parameter scale, multiplier 3 is taken into account
+ // in TanhPrepare function and it is included in
+ // input_multiplier already.
+
+ if (input_multiplier == 0)
+ { // power of two case
+ input_multiplier = 3 << input_left_shift;
+ input_left_shift = 0;
+ }
+
+ int32_t round = (input_left_shift > 0) ? 1 << (input_left_shift - 1) : 0;
+
+ for (int i = 0; i < flat_size; ++i, ptr_input_data++, ptr_output_data++)
+ {
+ int32_t input_data = ((*ptr_input_data) * input_multiplier + round) >> input_left_shift;
+
+ uint32_t abs_input_data = abs(input_data);
+ uint32_t uh = abs_input_data >> 8;
+ int32_t result;
+
+ if (uh >= 255)
+ {
+ // Saturate to maximum.
+ result = 0xFFFF << 8;
+ }
+ else
+ {
+ uint32_t ua = sigmoid_table_uint16[uh];
+ uint32_t ub = sigmoid_table_uint16[uh + 1];
+
+ uint8_t ut = abs_input_data & 0xFF;
+
+ result = (ua << 8) + ut * (ub - ua);
+ }
+
+ result = (input_data >= 0) ? (result - (1 << (14 + 9)) + (1 << (9 - 2)))
+ : (-result + (1 << (14 + 9)) + (1 << (9 - 2)) - 1);
+
+ // Convert back to 16-bit.
+ result >>= (9 - 1);
+
+ *ptr_output_data = result;
+ }
+}
+
+#if 0
+inline void Tanh(int32_t input_zero_point, int32_t input_range_radius,
+ int32_t input_multiplier, int32_t input_shift,
+ const int flat_size, const int8_t* input_data, int8_t* output_data) {
+ // Integer bits must be in sync with Prepare() function.
+ static constexpr int32_t kInputIntegerBits = 4;
+ static constexpr int32_t kOutputScale = 7;
+ static constexpr int32_t kMinInt8 = std::numeric_limits<int8_t>::min();
+ static constexpr int32_t kMaxInt8 = std::numeric_limits<int8_t>::max();
+
+ for (int i = 0; i < flat_size; ++i) {
+ const int32_t input =
+ static_cast<int32_t>(input_data[i]) - input_zero_point;
+ if (input <= -input_range_radius) {
+ output_data[i] = kMinInt8;
+ } else if (input >= input_range_radius) {
+ output_data[i] = kMaxInt8;
+ } else {
+ const int32_t input_in_q4 =
+ multiplyByQuantizedMultiplier(input, input_multiplier, input_shift);
+ const int32_t output_in_q0 = std::tanh(input_in_q4);
+
+ int32_t output_in_q24 =
+ roundingDivideByPOT(output_in_q0, 31 - kOutputScale);
+ output_in_q24 = std::min(std::max(output_in_q24, kMinInt8), kMaxInt8);
+ output_data[i] = static_cast<int8_t>(output_in_q24);
+ }
+ }
+}
+#endif // 0
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_TANH_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALTranspose.h b/onert-micro/luci-interpreter/pal/common/PALTranspose.h
new file mode 100644
index 000000000..3381992c8
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/PALTranspose.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2020 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_TRANSPOSE_H
+#define LUCI_INTERPRETER_PAL_TRANSPOSE_H
+
+#include "PALUtils.h"
+#include "ProcessBroadcastShapes.h"
+
+namespace luci_interpreter_pal
+{
+template <typename T, int N>
+void TransposeImpl(const TransposeParams &params,
+ const luci_interpreter::RuntimeShape &unextended_input_shape,
+ const T *input_data,
+ const luci_interpreter::RuntimeShape &unextended_output_shape, T *output_data)
+{
+ const int unextended_input_size = unextended_input_shape.dimensionsCount();
+ const int unextended_output_size = unextended_output_shape.dimensionsCount();
+
+ const int input_ext_size = N - unextended_input_size;
+ const int output_ext_size = N - unextended_output_size;
+ NdArrayDesc<N> input_desc;
+ NdArrayDesc<N> output_desc;
+ copyDimsToDesc(luci_interpreter::RuntimeShape::extendedShape(N, unextended_input_shape),
+ &input_desc);
+ copyDimsToDesc(luci_interpreter::RuntimeShape::extendedShape(N, unextended_output_shape),
+ &output_desc);
+
+ // The perm data is extended to match the output, each index incremented by
+ // the amount of front padding of the input shape.
+ int extended_perm[N];
+ for (int i = 0; i < N; ++i)
+ {
+ extended_perm[i] = i < output_ext_size ? i : params.perm[i - output_ext_size] + input_ext_size;
+ }
+
+ // Permutes the input shape so we don't need to permute the indexes inside
+ // the loop. Check to make sure output_dims is matching input_dims.
+ NdArrayDesc<N> perm_input_desc;
+ for (int k = 0; k < N; ++k)
+ {
+ perm_input_desc.extents[k] = input_desc.extents[extended_perm[k]];
+ perm_input_desc.strides[k] = input_desc.strides[extended_perm[k]];
+ }
+
+ // Naive transpose loop (iterate on output index and compute input index).
+ auto tranpose_func = [&](int indexes[N]) {
+ output_data[subscriptToIndex(output_desc, indexes)] =
+ input_data[subscriptToIndex(perm_input_desc, indexes)];
+ };
+ NDOpsHelper<N>(output_desc, tranpose_func);
+}
+
+template <typename T, int N = 5>
+void Transpose(const TransposeParams &params,
+ const luci_interpreter::RuntimeShape &unextended_input_shape, const T *input_data,
+ const luci_interpreter::RuntimeShape &unextended_output_shape, T *output_data)
+{
+ // Transpose kernel only does rearranging values not numeric evaluations on
+ // each cell. It's safe to implement per size of scalar type and this trick
+ // keeps the total code size in a reasonable range.
+ switch (sizeof(T))
+ {
+ case 1:
+ TransposeImpl<int8_t, N>(params, unextended_input_shape,
+ reinterpret_cast<const int8_t *>(input_data),
+ unextended_output_shape, reinterpret_cast<int8_t *>(output_data));
+ break;
+ case 2:
+ TransposeImpl<int16_t, N>(params, unextended_input_shape,
+ reinterpret_cast<const int16_t *>(input_data),
+ unextended_output_shape, reinterpret_cast<int16_t *>(output_data));
+ break;
+
+ case 4:
+ TransposeImpl<int32_t, N>(params, unextended_input_shape,
+ reinterpret_cast<const int32_t *>(input_data),
+ unextended_output_shape, reinterpret_cast<int32_t *>(output_data));
+ break;
+ case 8:
+ TransposeImpl<int64_t, N>(params, unextended_input_shape,
+ reinterpret_cast<const int64_t *>(input_data),
+ unextended_output_shape, reinterpret_cast<int64_t *>(output_data));
+ break;
+ }
+}
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_TRANSPOSE_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALUnidirectionalSequenceLSTMCommon.h b/onert-micro/luci-interpreter/pal/common/PALUnidirectionalSequenceLSTMCommon.h
new file mode 100644
index 000000000..ad9631cf2
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/PALUnidirectionalSequenceLSTMCommon.h
@@ -0,0 +1,567 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_UNIDIRECTIONAL_SEQUENCE_LSTM_COMMON_H
+#define LUCI_INTERPRETER_PAL_UNIDIRECTIONAL_SEQUENCE_LSTM_COMMON_H
+
+#include "kernels/UnidirectionalSequenceLSTM.h"
+#include "PALTanh.h"
+#include "PALLogistic.h"
+#include "PALFullyConnected.h"
+#include "PALMul.h"
+#include "PALUtils.h"
+
+namespace luci_interpreter_pal
+{
+namespace lstm_internal
+{
+namespace
+{
+// Possible fused activation functions.
+typedef enum
+{
+ kTfLiteActNone = 0,
+ kTfLiteActRelu,
+ kTfLiteActReluN1To1, // min(max(-1, x), 1)
+ kTfLiteActRelu6, // min(max(0, x), 6)
+ kTfLiteActTanh,
+ kTfLiteActSignBit,
+ kTfLiteActSigmoid,
+} FusedActivation;
+
+} // namespace
+
+#ifndef DIS_QUANT
+
+template <typename InputType, typename OutputType>
+void mulElementwise(int size, const ArithmeticParams *params, const InputType *input1_data,
+ const InputType *input2_data, OutputType *output_data)
+{
+ for (int i = 0; i < size; ++i)
+ {
+ const int32_t input1_val = params->input1_offset + input1_data[i];
+ const int32_t input2_val = params->input2_offset + input2_data[i];
+ const int32_t unclamped_result =
+ params->output_offset + multiplyByQuantizedMultiplier(input1_val * input2_val,
+ params->output_multiplier,
+ params->output_shift);
+ const int32_t clamped_output =
+ std::min(params->quantized_activation_max,
+ std::max(params->quantized_activation_min, unclamped_result));
+ output_data[i] = static_cast<OutputType>(clamped_output);
+ }
+}
+
+// Input and output have the same shape in LSTM
+void mul(const luci_interpreter::RuntimeShape &shape, const ArithmeticParams *params,
+ const int16_t *input1_data, const int16_t *input2_data, int8_t *output_data)
+{
+ return mulElementwise<int16_t, int8_t>(shape.flatSize(), params, input1_data, input2_data,
+ output_data);
+}
+
+// Input and output have the same shape in LSTM
+void mul(const luci_interpreter::RuntimeShape &shape, const ArithmeticParams *params,
+ const int16_t *input1_data, const int16_t *input2_data, int16_t *output_data)
+{
+ return mulElementwise(shape.flatSize(), params, input1_data, input2_data, output_data);
+}
+
+void addElementWise(const int16_t *input_1, const int16_t *input_2, int n_batch, int n_input,
+ int16_t *output)
+{
+ for (int batch = 0; batch < n_batch; ++batch)
+ {
+ for (int i = 0; i < n_input; ++i)
+ {
+ const int index = batch * n_input + i;
+ int32_t sum = input_1[index] + input_2[index];
+ const int32_t sum_clamped =
+ std::min(static_cast<int32_t>(std::numeric_limits<int16_t>::max()),
+ std::max(static_cast<int32_t>(std::numeric_limits<int16_t>::min()), sum));
+ output[index] = static_cast<int16_t>(sum_clamped);
+ }
+ }
+}
+
+void tanh(int32_t cell_state_scale_power, const luci_interpreter::RuntimeShape &input_data_shape,
+ int16_t *input_data, const luci_interpreter::RuntimeShape &output_data_shape,
+ int16_t *output_data)
+{
+ int32_t tanh_input_left_shift = (15 + cell_state_scale_power) - 3;
+ int32_t input_multiplier = 0;
+ if (tanh_input_left_shift < 0) /* handling negative shift value */
+ {
+ tanh_input_left_shift = -tanh_input_left_shift;
+ input_multiplier = 3;
+ }
+ const int flat_size = input_data_shape.flatSize();
+ luci_interpreter_pal::Tanh(input_multiplier, tanh_input_left_shift, flat_size, input_data,
+ output_data);
+}
+
+void sigmoid(const luci_interpreter::RuntimeShape &data_shape, int16_t *data)
+{
+ luci_interpreter_pal::Logistic(0, 0, data_shape.flatSize(), data, data);
+}
+
+void clipping(const int v_size, const luci_interpreter::lstm::CellStateInfo *cell_state_info,
+ int16_t *vector)
+{
+ for (int i = 0; i < v_size; i++)
+ {
+ vector[i] = std::max(std::min(cell_state_info->quantized_cell_clip, vector[i]),
+ static_cast<int16_t>(-cell_state_info->quantized_cell_clip));
+ }
+}
+#endif // DIS_QUANT
+
+#ifndef DIS_FLOAT
+// Input and output have the same shape in LSTM
+void mul(const luci_interpreter::RuntimeShape &shape, const ArithmeticParams *params,
+ const float *input1_data, const float *input2_data, float *output_data)
+{
+ const int flat_size = shape.flatSize();
+ return luci_interpreter_pal::Mul(*params, flat_size, input1_data, input2_data, output_data);
+}
+
+void addElementWise(const float *input_1, const float *input_2, int n_batch, int n_input,
+ float *output)
+{
+ for (int batch = 0; batch < n_batch; ++batch)
+ {
+ for (int i = 0; i < n_input; ++i)
+ {
+ const int index = batch * n_input + i;
+ output[index] = input_1[index] + input_2[index];
+ }
+ }
+}
+
+void tanh(int32_t, const luci_interpreter::RuntimeShape &input_data_shape, float *input_data,
+ const luci_interpreter::RuntimeShape &output_data_shape, float *output_data)
+{
+ const int flat_size = input_data_shape.flatSize();
+ luci_interpreter_pal::Tanh(flat_size, input_data, output_data);
+}
+
+void sigmoid(const luci_interpreter::RuntimeShape &data_shape, float *data)
+{
+ const int flat_size = data_shape.flatSize();
+ luci_interpreter_pal::Logistic(flat_size, data, data);
+}
+
+void clipping(const int v_size, const luci_interpreter::lstm::CellStateInfo *cell_state_info,
+ float *vector)
+{
+ for (int i = 0; i < v_size; i++)
+ {
+ vector[i] =
+ std::max(std::min(cell_state_info->cell_clip, vector[i]), -cell_state_info->cell_clip);
+ }
+}
+#endif // DIS_FLOAT
+
+// Size information about the LSTM kernel, which is deduced from tensors stored
+// in the flat buffer file.
+struct LstmSizeInfo
+{
+ bool time_major;
+ int32_t batch_size;
+ int32_t time_steps;
+ int32_t input_dimension;
+ int32_t state_dimension;
+};
+
+class LstmStepManager
+{
+public:
+ LstmStepManager() = delete;
+ // Does not take any ownership, and all pointers must refer to valid objects
+ // that outlive the one constructed.
+ explicit LstmStepManager(const LstmSizeInfo &size_info) : size_info_(size_info) {}
+
+ void updateTime()
+ {
+ current_time_ += 1;
+ // default as one batch per inference
+ int input_step = size_info_.input_dimension;
+ int output_step = size_info_.state_dimension;
+ // time major: batch inference
+ if (size_info_.time_major)
+ {
+ input_step = input_step * size_info_.batch_size;
+ output_step = output_step * size_info_.batch_size;
+ }
+
+ input_offset_ += input_step;
+ output_offset_ += output_step;
+ }
+
+ void updateBatch()
+ {
+ current_batch_ += 1;
+ // batch inference for time major: no action needed
+ if (size_info_.time_major)
+ {
+ return;
+ }
+ // otherwise: singe batch inference, go to the next batch
+ hidden_state_offset_ += size_info_.state_dimension;
+ cell_state_offset_ += size_info_.state_dimension;
+ }
+
+ void resetTime() { current_time_ = 0; }
+
+ luci_interpreter::RuntimeShape inputShape() const
+ {
+ int batch_size = 1;
+ if (size_info_.time_major)
+ {
+ batch_size = size_info_.batch_size;
+ }
+ const int dims[2] = {batch_size, size_info_.input_dimension};
+ const int32_t *dims_data = reinterpret_cast<const int32_t *>(dims);
+ return luci_interpreter::RuntimeShape(2, dims_data);
+ }
+
+ luci_interpreter::RuntimeShape stateShape() const
+ {
+ int batch_size = 1;
+ if (size_info_.time_major)
+ {
+ batch_size = size_info_.batch_size;
+ }
+ const int dims[2] = {batch_size, size_info_.state_dimension};
+ const int32_t *dims_data = reinterpret_cast<const int32_t *>(dims);
+ return luci_interpreter::RuntimeShape(2, dims_data);
+ }
+
+ int inputOffset() const { return input_offset_; }
+
+ int outputOffset() const { return output_offset_; }
+
+ int hiddenStateOffset() const { return hidden_state_offset_; }
+
+ int cellStateOffset() const { return cell_state_offset_; }
+
+private:
+ int32_t current_time_ = 0;
+ int32_t current_batch_ = 0;
+ int32_t input_offset_ = 0;
+ int32_t output_offset_ = 0;
+ int32_t hidden_state_offset_ = 0;
+ int32_t cell_state_offset_ = 0;
+
+ const LstmSizeInfo &size_info_;
+};
+
+// Calculates a single LSTM gate.
+// Implements the following formula:
+// gate = activate(FC(input) + FC(recurrent))
+// Activation is sigmoid except for the "cell" gate (configurable, usually tanh)
+template <typename ActivationType, typename WeightType, typename CellType, typename BiasType>
+void calculateLstmGate(const LstmStepManager *step_info,
+ const luci_interpreter::lstm::GateParameters *gate_params,
+ // Input FC
+ ActivationType *input_data, const circle::Tensor *input_weight,
+ const circle::Tensor *input_bias,
+ // Recurrent FC
+ ActivationType *recurrent_data, const circle::Tensor *recurrent_weight,
+ const circle::Tensor *recurrent_bias,
+ // Output
+ CellType *gate_output,
+ // Scratch arrays
+ CellType *fc_output_buffer, const FusedActivation activation,
+ luci_interpreter::BaseRuntimeGraph *runtime_graph)
+{
+ // Input FC
+ const auto gate_output_shape = step_info->stateShape();
+ {
+ FullyConnectedParams op_params{};
+ op_params.input_offset = gate_params->input_fc_params.input_offset;
+ op_params.weights_offset = gate_params->input_fc_params.weights_offset;
+ op_params.output_offset = gate_params->input_fc_params.output_offset;
+ op_params.output_multiplier = gate_params->input_fc_params.output_multiplier;
+ op_params.output_shift = gate_params->input_fc_params.output_shift;
+ op_params.quantized_activation_min = gate_params->input_fc_params.quantized_activation_min;
+ op_params.quantized_activation_max = gate_params->input_fc_params.quantized_activation_max;
+ op_params.float_activation_max = gate_params->input_fc_params.float_activation_max;
+ op_params.float_activation_min = gate_params->input_fc_params.float_activation_min;
+
+ int32_t input_weight_shape[luci_interpreter::kMaxSmallSize];
+ luci_interpreter::kernels::getTensorDims(input_weight, runtime_graph, input_weight_shape);
+
+ FullyConnected(op_params, step_info->inputShape().dimsData(),
+ input_data + step_info->inputOffset(), input_weight_shape,
+ luci_interpreter::kernels::getTensorData<WeightType>(
+ runtime_graph->getConstDataByTensor(input_weight)),
+ luci_interpreter::kernels::getTensorData<BiasType>(
+ runtime_graph->getConstDataByTensor(input_bias)),
+ gate_output_shape.dimsData(), gate_output);
+ }
+
+ // Recurrent FC
+ {
+ FullyConnectedParams op_params{};
+ op_params.input_offset = gate_params->recurrent_fc_params.input_offset;
+ op_params.weights_offset = gate_params->recurrent_fc_params.weights_offset;
+ op_params.output_offset = gate_params->recurrent_fc_params.output_offset;
+ op_params.output_multiplier = gate_params->recurrent_fc_params.output_multiplier;
+ op_params.output_shift = gate_params->recurrent_fc_params.output_shift;
+ op_params.quantized_activation_min = gate_params->recurrent_fc_params.quantized_activation_min;
+ op_params.quantized_activation_max = gate_params->recurrent_fc_params.quantized_activation_max;
+ op_params.float_activation_max = gate_params->recurrent_fc_params.float_activation_max;
+ op_params.float_activation_min = gate_params->recurrent_fc_params.float_activation_min;
+
+ int32_t recurrent_weight_shape[luci_interpreter::kMaxSmallSize];
+ luci_interpreter::kernels::getTensorDims(recurrent_weight, runtime_graph,
+ recurrent_weight_shape);
+
+ FullyConnected(op_params, step_info->stateShape().dimsData(),
+ recurrent_data + step_info->hiddenStateOffset(), recurrent_weight_shape,
+ luci_interpreter::kernels::getTensorData<WeightType>(
+ runtime_graph->getConstDataByTensor(recurrent_weight)),
+ luci_interpreter::kernels::getTensorData<BiasType>(
+ runtime_graph->getConstDataByTensor(recurrent_bias)),
+ gate_output_shape.dimsData(), fc_output_buffer);
+
+ addElementWise(gate_output, fc_output_buffer, /*n_batch=*/gate_output_shape.dimsData()[0],
+ /*n_state=*/gate_output_shape.dimsData()[1], gate_output);
+
+ switch (activation)
+ {
+ case FusedActivation::kTfLiteActSigmoid:
+ sigmoid(gate_output_shape, gate_output);
+ break;
+ case FusedActivation::kTfLiteActTanh:
+ {
+ // Set the scale power to -12 to avoid shift
+ tanh(/*cell_state_scale_power=*/-12, gate_output_shape, gate_output, gate_output_shape,
+ gate_output);
+ }
+ break;
+ default:
+ // Only Sigmoid or Tanh is used.
+ assert(false && "Only Sigmoid or Tanh is used");
+ }
+ }
+}
+
+// Update the hidden state of the LSTM kernel using the following formula:
+// updated_hidden_state = Tanh(updated_cell_state) * output_gate_output, * means
+// element wise multiplication
+template <typename CellType, typename ActivationType>
+void updateLstmHidden(const LstmStepManager *step_info, CellType *cell_state_data_base,
+ ActivationType *hidden_state_data, const CellType *output_gate_output,
+ const ArithmeticParams *mul_params, int32_t cell_state_scale_power,
+ CellType *buffer)
+{
+ auto cell_state_shape = step_info->stateShape();
+ CellType *cell_state_data = cell_state_data_base + step_info->cellStateOffset();
+ // Tanh(cell_state)
+ tanh(cell_state_scale_power, cell_state_shape, cell_state_data, cell_state_shape, buffer);
+ // Update the hidden state
+ mul(cell_state_shape, mul_params, buffer, output_gate_output,
+ hidden_state_data + step_info->hiddenStateOffset());
+}
+
+// Update the cell state using the output from the forget gate, input gate, and
+// cell gate Formula: updated_cell_state = forget_gate_output*cell_state +
+// input_gate_output * cell_gate_output, where * denotes element wise
+// multiplication
+template <typename CellType>
+void updateLstmCell(const LstmStepManager *step_info, CellType *cell_state_data,
+ // Gate outputs
+ CellType *forget_gate_output, const CellType *input_gate_output,
+ const CellType *cell_gate_output,
+ // Mul parameters
+ const ArithmeticParams &forget_cell_mul_params,
+ const ArithmeticParams &input_mul_params,
+ const luci_interpreter::lstm::CellStateInfo *cell_state_info, CellType *buffer)
+{
+ auto cell_state_shape = step_info->stateShape();
+ // Forget Gate x Cell State
+ mul(cell_state_shape, &forget_cell_mul_params, forget_gate_output,
+ cell_state_data + step_info->cellStateOffset(),
+ cell_state_data + step_info->cellStateOffset());
+ // Input Gate x Cell Gate
+ mul(cell_state_shape, &input_mul_params, input_gate_output, cell_gate_output, buffer);
+
+ // Update the cell state
+ addElementWise(cell_state_data + step_info->cellStateOffset(), buffer,
+ /*n_batch=*/cell_state_shape.dimsData()[0],
+ /*n_state=*/cell_state_shape.dimsData()[1],
+ cell_state_data + step_info->cellStateOffset());
+
+ if (cell_state_info->cell_clip > 0)
+ {
+ clipping(cell_state_shape.flatSize(), cell_state_info,
+ cell_state_data + step_info->cellStateOffset());
+ }
+}
+
+template <typename ActivationType, typename WeightType, typename CellType, typename BiasType>
+void lstmStep(luci_interpreter::lstm::LSTMStruct *lstm_struct,
+ luci_interpreter::lstm::LSTMParameters *lstm_params, LstmStepManager *step_info,
+ luci_interpreter::lstm::CellStateInfo *cell_state_info,
+ ActivationType *output_state_data, CellType *cell_state_data, CellType *scratch0,
+ CellType *scratch1, CellType *scratch2, CellType *scratch3,
+ luci_interpreter::BaseRuntimeGraph *runtime_graph)
+{
+ /*Step1: Calculate gate outputs to prepare cell state update*/
+ CellType *gate_internal_buffer = scratch3;
+ CellType *forget_gate_output = scratch0;
+
+ auto input_data = luci_interpreter::kernels::getTensorData<ActivationType>(
+ runtime_graph->getDataByTensor(lstm_struct->input()));
+
+ calculateLstmGate<ActivationType, WeightType, CellType, BiasType>(
+ step_info, &lstm_params->forget_gate_parameters,
+ // Input FC
+ input_data, lstm_struct->input_to_forget_weights(), lstm_struct->forget_gate_bias(),
+ // Recurrent FC
+ output_state_data, lstm_struct->recurrent_to_forget_weights(), nullptr,
+ // Output
+ forget_gate_output, gate_internal_buffer, FusedActivation::kTfLiteActSigmoid, runtime_graph);
+
+ // Input Gate calculation;
+ CellType *input_gate_output = scratch1;
+ calculateLstmGate<ActivationType, WeightType, CellType, BiasType>(
+ step_info, &lstm_params->input_gate_parameters,
+ // Input FC
+ input_data, lstm_struct->input_to_input_weights(), lstm_struct->input_gate_bias(),
+ // Recurrent FC
+ output_state_data, lstm_struct->recurrent_to_input_weights(),
+ /*recurrent_bias*/ nullptr,
+ // Output
+ input_gate_output,
+ // Scratch arrays
+ gate_internal_buffer, FusedActivation::kTfLiteActSigmoid, runtime_graph);
+
+ // Cell Gate calculation
+ CellType *cell_gate_output = scratch2;
+ calculateLstmGate<ActivationType, WeightType, CellType, BiasType>(
+ step_info, &lstm_params->cell_gate_parameters,
+ // Input FC
+ input_data, lstm_struct->input_to_cell_weights(), lstm_struct->cell_gate_bias(),
+ // Recurrent FC
+ output_state_data, lstm_struct->recurrent_to_cell_weights(),
+ /*recurrent_bias*/ nullptr,
+ // Output
+ cell_gate_output,
+ // Scratch arrays
+ gate_internal_buffer, FusedActivation::kTfLiteActTanh, runtime_graph);
+
+ /*Step2: update the cell state */
+ {
+ // const InterGateParameters& inter_gate_params = op_data.inter_gate_parameters;
+ CellType *updated_input_buffer = scratch1; // reuse buffer
+
+ updateLstmCell<CellType>(
+ step_info, cell_state_data, forget_gate_output, input_gate_output, cell_gate_output,
+ lstm_params->inter_gate_parameters.forget_cell_mul_params,
+ lstm_params->inter_gate_parameters.input_mul_params, cell_state_info, updated_input_buffer);
+ }
+
+ {
+ /*Step3: update the hidden state */
+ CellType *output_gate_output = scratch1; // reuse buffer
+ calculateLstmGate<ActivationType, WeightType, CellType, BiasType>(
+ step_info, &lstm_params->output_gate_parameters,
+ // Input FC
+ input_data, lstm_struct->input_to_output_weights(), lstm_struct->output_gate_bias(),
+ // Recurrent FC
+ output_state_data, lstm_struct->recurrent_to_output_weights(), nullptr,
+ // Output
+ output_gate_output,
+ // Scratch arrays
+ gate_internal_buffer, FusedActivation::kTfLiteActSigmoid, runtime_graph);
+ CellType *tanh_activated_cell_buffer = scratch0; // reuse buffer
+ updateLstmHidden<CellType, ActivationType>(
+ step_info, cell_state_data, output_state_data, output_gate_output,
+ &lstm_params->inter_gate_parameters.output_mul_params,
+ cell_state_info->cell_state_scale_power, tanh_activated_cell_buffer);
+
+ ActivationType *output_ptr = luci_interpreter::kernels::getTensorData<ActivationType>(
+ runtime_graph->getDataByTensor(lstm_struct->output()));
+ std::memcpy(output_ptr + step_info->outputOffset(),
+ output_state_data + step_info->hiddenStateOffset(),
+ step_info->stateShape().flatSize() * sizeof(ActivationType));
+ }
+}
+
+} // namespace lstm_internal
+
+// Evaluate the LSTM kernel with (potential) multi-steps and multi-batch input
+template <typename ActivationType, typename WeightType, typename CellType, typename BiasType>
+void evalLSTM(luci_interpreter::lstm::LSTMStruct *lstm_struct,
+ luci_interpreter::lstm::LSTMParameters *lstm_params,
+ luci_interpreter::lstm::CellStateInfo *cell_state_info,
+ ActivationType *output_state_data, CellType *cell_state_data, CellType *scratch0,
+ CellType *scratch1, CellType *scratch2, CellType *scratch3,
+ luci_interpreter::BaseRuntimeGraph *runtime_graph)
+{
+ lstm_internal::LstmSizeInfo size_info;
+
+ size_info.time_major = lstm_struct->options->time_major();
+ size_info.batch_size = size_info.time_major
+ ? luci_interpreter::Tensor::dim(lstm_struct->input(), 1)
+ : luci_interpreter::Tensor::dim(lstm_struct->input(), 0);
+ size_info.time_steps = size_info.time_major
+ ? luci_interpreter::Tensor::dim(lstm_struct->input(), 0)
+ : luci_interpreter::Tensor::dim(lstm_struct->input(), 1);
+ size_info.input_dimension = luci_interpreter::Tensor::dim(lstm_struct->input(), 2);
+ size_info.state_dimension = luci_interpreter::Tensor::dim(lstm_struct->output_state(), 1);
+
+ lstm_internal::LstmStepManager step_info(size_info);
+
+ // time is the first dimention, enable batch computation
+ if (size_info.time_major)
+ {
+ for (int t = 0; t < size_info.time_steps; t++)
+ {
+ lstm_internal::lstmStep<ActivationType, WeightType, CellType, BiasType>(
+ lstm_struct, lstm_params, &step_info, cell_state_info, output_state_data, cell_state_data,
+ scratch0, scratch1, scratch2, scratch3, runtime_graph);
+ // prepare for the next time step
+ step_info.updateTime();
+ }
+ }
+ else
+ {
+ // batch first, unable to size the input data. single batch inference
+ for (int b = 0; b < size_info.batch_size; b++)
+ {
+ for (int t = 0; t < size_info.time_steps; t++)
+ {
+ lstm_internal::lstmStep<ActivationType, WeightType, CellType, BiasType>(
+ lstm_struct, lstm_params, &step_info, cell_state_info, output_state_data, cell_state_data,
+ scratch0, scratch1, scratch2, scratch3, runtime_graph);
+ // prepare for the next time step
+ step_info.updateTime();
+ }
+ // prepare for the next batch
+ step_info.updateBatch();
+ step_info.resetTime();
+ }
+ }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_UNIDIRECTIONAL_SEQUENCE_LSTM_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALUtils.h b/onert-micro/luci-interpreter/pal/common/PALUtils.h
new file mode 100644
index 000000000..1e05bfc7b
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/PALUtils.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_UTILS_H
+#define LUCI_INTERPRETER_PAL_UTILS_H
+
+#include <cassert>
+
+namespace luci_interpreter_pal
+{
+
+// Table of sigmoid(i/24) at 0.16 format - 256 elements.
+// We use combined sigmoid and tanh look-up table, since
+// tanh(x) = 2*sigmoid(2*x) -1.
+// Both functions are symmetric, so the LUT table is only needed
+// for the absolute value of the input.
+static const uint16_t sigmoid_table_uint16[256] = {
+ 32768, 33451, 34133, 34813, 35493, 36169, 36843, 37513, 38180, 38841, 39498, 40149, 40794, 41432,
+ 42064, 42688, 43304, 43912, 44511, 45102, 45683, 46255, 46817, 47369, 47911, 48443, 48964, 49475,
+ 49975, 50464, 50942, 51409, 51865, 52311, 52745, 53169, 53581, 53983, 54374, 54755, 55125, 55485,
+ 55834, 56174, 56503, 56823, 57133, 57433, 57724, 58007, 58280, 58544, 58800, 59048, 59288, 59519,
+ 59743, 59959, 60168, 60370, 60565, 60753, 60935, 61110, 61279, 61441, 61599, 61750, 61896, 62036,
+ 62172, 62302, 62428, 62549, 62666, 62778, 62886, 62990, 63090, 63186, 63279, 63368, 63454, 63536,
+ 63615, 63691, 63765, 63835, 63903, 63968, 64030, 64090, 64148, 64204, 64257, 64308, 64357, 64405,
+ 64450, 64494, 64536, 64576, 64614, 64652, 64687, 64721, 64754, 64786, 64816, 64845, 64873, 64900,
+ 64926, 64950, 64974, 64997, 65019, 65039, 65060, 65079, 65097, 65115, 65132, 65149, 65164, 65179,
+ 65194, 65208, 65221, 65234, 65246, 65258, 65269, 65280, 65291, 65301, 65310, 65319, 65328, 65337,
+ 65345, 65352, 65360, 65367, 65374, 65381, 65387, 65393, 65399, 65404, 65410, 65415, 65420, 65425,
+ 65429, 65433, 65438, 65442, 65445, 65449, 65453, 65456, 65459, 65462, 65465, 65468, 65471, 65474,
+ 65476, 65479, 65481, 65483, 65485, 65488, 65489, 65491, 65493, 65495, 65497, 65498, 65500, 65501,
+ 65503, 65504, 65505, 65507, 65508, 65509, 65510, 65511, 65512, 65513, 65514, 65515, 65516, 65517,
+ 65517, 65518, 65519, 65520, 65520, 65521, 65522, 65522, 65523, 65523, 65524, 65524, 65525, 65525,
+ 65526, 65526, 65526, 65527, 65527, 65528, 65528, 65528, 65529, 65529, 65529, 65529, 65530, 65530,
+ 65530, 65530, 65531, 65531, 65531, 65531, 65531, 65532, 65532, 65532, 65532, 65532, 65532, 65533,
+ 65533, 65533, 65533, 65533, 65533, 65533, 65533, 65534, 65534, 65534, 65534, 65534, 65534, 65534,
+ 65534, 65534, 65534, 65535};
+
+inline std::int32_t saturatingRoundingDoublingHighMul(std::int32_t a, std::int32_t b)
+{
+ bool overflow = a == b && a == std::numeric_limits<std::int32_t>::min();
+ std::int64_t a_64(a);
+ std::int64_t b_64(b);
+ std::int64_t ab_64 = a_64 * b_64;
+ std::int32_t nudge = ab_64 >= 0 ? (1 << 30) : (1 - (1 << 30));
+ std::int32_t ab_x2_high32 = static_cast<std::int32_t>((ab_64 + nudge) / (1ll << 31));
+ return overflow ? std::numeric_limits<std::int32_t>::max() : ab_x2_high32;
+}
+
+// Correctly-rounded-to-nearest division by a power-of-two.
+// Also known as a rounding arithmetic right shift.
+inline int32_t roundingDivideByPOT(int32_t x, int32_t exponent)
+{
+ assert(exponent >= 0);
+ assert(exponent <= 31);
+ const int32_t mask = int32_t((1ll << exponent) - 1);
+ const int32_t zero = int32_t(0);
+ const int32_t one = int32_t(1);
+ const int32_t remainder = x & mask;
+ const int32_t threshold = (mask >> 1) + ((x < zero ? one : zero) & one);
+ return (x >> exponent) + ((remainder > threshold ? one : zero) & one);
+}
+
+inline int32_t multiplyByQuantizedMultiplier(int32_t x, int32_t quantized_multiplier, int shift)
+{
+ int left_shift = shift > 0 ? shift : 0;
+ int right_shift = shift > 0 ? 0 : -shift;
+ return roundingDivideByPOT(
+ saturatingRoundingDoublingHighMul(x * (1 << left_shift), quantized_multiplier), right_shift);
+}
+
+inline int32_t multiplyByQuantizedMultiplierSmallerThanOneExp(int32_t x,
+ int32_t quantized_multiplier,
+ int left_shift)
+{
+ return roundingDivideByPOT(saturatingRoundingDoublingHighMul(x, quantized_multiplier),
+ -left_shift);
+}
+
+template <typename P> inline void getActivationParams(const P &params, int32_t *min, int32_t *max)
+{
+ *min = params.quantized_activation_min;
+ *max = params.quantized_activation_max;
+}
+
+template <typename P> inline void getActivationParams(const P &params, float *min, float *max)
+{
+ *min = params.float_activation_min;
+ *max = params.float_activation_max;
+}
+
+template <typename P> inline void getActivationParams(const P &params, int64_t *min, int64_t *max)
+{
+ *min = params.int64_activation_min;
+ *max = params.int64_activation_max;
+}
+
+// Gets offset of index if reducing on axis. When reducing, the flattened offset
+// will not change, if the input index changes on the given axis. For example,
+// if you have a 3D tensor and you are reducing to 2D by eliminating axis 0,
+// then index (0, 1, 2) and index (1, 1, 2) will map to the same flattened
+// offset.
+inline size_t reducedOutputOffset(const int num_dims, const int *dims, const int *index,
+ const int num_axis, const int *axis)
+{
+ if (num_dims == 0)
+ {
+ return 0;
+ }
+ size_t offset = 0;
+ for (int idx = 0; idx < num_dims; ++idx)
+ {
+ // if we need to skip this axis
+ bool is_axis = false;
+ if (axis != nullptr)
+ {
+ for (int axis_idx = 0; axis_idx < num_axis; ++axis_idx)
+ {
+ if (idx == axis[axis_idx])
+ {
+ is_axis = true;
+ break;
+ }
+ }
+ }
+ if (!is_axis)
+ {
+ offset = offset * static_cast<size_t>(dims[idx]) + static_cast<size_t>(index[idx]);
+ }
+ }
+ return offset;
+}
+
+// Gets next index to iterate through a multidimensional array.
+inline bool nextIndex(const int num_dims, const int *dims, int *current)
+{
+ if (num_dims == 0)
+ {
+ return false;
+ }
+ int carry = 1;
+ for (int idx = num_dims - 1; idx >= 0; --idx)
+ {
+ int current_val = current[idx] + carry;
+ if (dims[idx] == current_val)
+ {
+ current[idx] = 0;
+ }
+ else
+ {
+ current[idx] = current_val;
+ carry = 0;
+ break;
+ }
+ }
+ return (carry == 0);
+}
+
+// Get common shape dim, assert that they all agree.
+inline int MatchingDim(const luci_interpreter::RuntimeShape &shape1, int index1,
+ const luci_interpreter::RuntimeShape &shape2, int index2)
+{
+ assert(shape1.dims(index1) == shape2.dims(index2));
+ return shape1.dims(index1);
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_UTILS_H
diff --git a/onert-micro/luci-interpreter/pal/common/Params.h b/onert-micro/luci-interpreter/pal/common/Params.h
new file mode 100644
index 000000000..0dea29432
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/Params.h
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_PARAMS_H
+#define LUCI_INTERPRETER_PAL_PARAMS_H
+
+namespace luci_interpreter_pal
+{
+
+struct PadParams
+{
+ int8_t left_padding_count;
+ int32_t left_padding[5];
+ int8_t right_padding_count;
+ int32_t right_padding[5];
+};
+
+struct FullyConnectedParams
+{
+ int32_t input_offset;
+ int32_t weights_offset;
+ int32_t output_offset;
+ int32_t output_multiplier;
+ int output_shift;
+ // uint8_t, etc, activation params.
+ int32_t quantized_activation_min;
+ int32_t quantized_activation_max;
+ // float activation params.
+ float float_activation_min;
+ float float_activation_max;
+ // Mark the operands as cacheable if they are unchanging, e.g. weights.
+ bool lhs_cacheable;
+ bool rhs_cacheable;
+};
+
+enum class PaddingType : uint8_t
+{
+ None,
+ Same,
+ Valid
+};
+
+struct PaddingValues
+{
+ int16_t width;
+ int16_t height;
+ // offset is used for calculating "remaining" padding, for example, `width`
+ // is 1 and `width_offset` is 1, so padding_left is 1 while padding_right is
+ // 1 + 1 = 2.
+ int16_t width_offset;
+ // Same as width_offset except it's over the height dimension.
+ int16_t height_offset;
+};
+
+struct ConvParams
+{
+ PaddingType padding_type;
+ PaddingValues padding_values;
+ int16_t stride_width;
+ int16_t stride_height;
+ int16_t dilation_width_factor;
+ int16_t dilation_height_factor;
+ // uint8_t inference params.
+ int32_t input_offset;
+ int32_t weights_offset;
+ int32_t output_offset;
+ int32_t output_multiplier;
+ int output_shift;
+ // uint8_t, etc, activation params.
+ int32_t quantized_activation_min;
+ int32_t quantized_activation_max;
+ // float activation params.
+ float float_activation_min;
+ float float_activation_max;
+};
+
+enum class BroadcastableOpCategory : uint8_t
+{
+ kNone,
+ kNonBroadcast, // Matching input shapes.
+ kFirstInputBroadcastsFast, // Fivefold nested loops.
+ kSecondInputBroadcastsFast, // Fivefold nested loops.
+ kGenericBroadcast, // Fall-back.
+ kScalarFirstBroadcast, // Scalar
+ kScalarSecondBroadcast, // Scalar
+};
+
+struct ConcatenationParams
+{
+ int8_t axis;
+ const int32_t *input_zeropoint;
+ const float *input_scale;
+ uint16_t inputs_count;
+ int32_t output_zeropoint;
+ float output_scale;
+};
+
+struct TransposeParams
+{
+ int8_t perm_count;
+ int32_t perm[5];
+};
+
+struct ComparisonParams
+{
+ // uint8_t inference params.
+ int left_shift;
+ int32_t input1_offset;
+ int32_t input1_multiplier;
+ int input1_shift;
+ int32_t input2_offset;
+ int32_t input2_multiplier;
+ int input2_shift;
+ // Shape dependent / common to inference types.
+ bool is_broadcast;
+};
+
+struct StridedSliceParams
+{
+ int8_t start_indices_count;
+ int32_t start_indices[5];
+ int8_t stop_indices_count;
+ int32_t stop_indices[5];
+ int8_t strides_count;
+ int32_t strides[5];
+
+ int16_t begin_mask;
+ int16_t ellipsis_mask;
+ int16_t end_mask;
+ int16_t new_axis_mask;
+ int16_t shrink_axis_mask;
+};
+
+// For Add, Sub, Mul ops.
+struct ArithmeticParams
+{
+ // Shape dependent / common to data / op types.
+ BroadcastableOpCategory broadcast_category;
+ // uint8_t inference params.
+ int32_t input1_offset;
+ int32_t input2_offset;
+ int32_t output_offset;
+ int32_t output_multiplier;
+ int output_shift;
+ // Add / Sub, not Mul, uint8_t inference params.
+ int left_shift;
+ int32_t input1_multiplier;
+ int input1_shift;
+ int32_t input2_multiplier;
+ int input2_shift;
+ // uint8_t, etc, activation params.
+ int32_t quantized_activation_min;
+ int32_t quantized_activation_max;
+ // float activation params.
+ float float_activation_min;
+ float float_activation_max;
+ // int64_t activation params.
+ int64_t int64_activation_min;
+ int64_t int64_activation_max;
+
+ // Processed output dimensions.
+ // Let input "a" be the one that broadcasts in the faster-changing dimension.
+ // Then, after coalescing, for shapes {a0, a1, a2, a3, a4} and
+ // {b0, b1, b2, b3, b4},
+ // broadcast_shape[4] = b0 = a0.
+ // broadcast_shape[3] = b1; a1 = 1.
+ // broadcast_shape[2] = b2 = a2.
+ // broadcast_shape[1] = a3; b3 = 1.
+ // broadcast_shape[0] = b4 = a4.
+ int broadcast_shape[5];
+};
+
+enum class FusedActivationFunctionType : uint8_t
+{
+ kNone,
+ kRelu6,
+ kRelu1,
+ kRelu
+};
+
+struct PoolParams
+{
+ FusedActivationFunctionType activation;
+ PaddingType padding_type;
+ PaddingValues padding_values;
+ int stride_height;
+ int stride_width;
+ int filter_height;
+ int filter_width;
+ // uint8_t, etc, activation params.
+ int32_t quantized_activation_min;
+ int32_t quantized_activation_max;
+ // float activation params.
+ float float_activation_min;
+ float float_activation_max;
+};
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_PARAMS_H
diff --git a/onert-micro/luci-interpreter/pal/common/ProcessBroadcastShapes.h b/onert-micro/luci-interpreter/pal/common/ProcessBroadcastShapes.h
new file mode 100644
index 000000000..05ce8024e
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/common/ProcessBroadcastShapes.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_PROCESS_BROADCAST_SHAPES_H
+#define LUCI_INTERPRETER_PAL_PROCESS_BROADCAST_SHAPES_H
+
+namespace luci_interpreter_pal
+{
+
+// DO NOT USE THIS STRUCT FOR NEW FUNCTIONALITY BEYOND IMPLEMENTING
+// BROADCASTING.
+//
+// NdArrayDesc<N> describes the shape and memory layout of an N-dimensional
+// rectangular array of numbers.
+//
+// NdArrayDesc<N> is basically identical to Dims<N> defined in types.h.
+// However, as Dims<N> is to be deprecated, this class exists as an adaptor
+// to enable simple unoptimized implementations of element-wise broadcasting
+// operations.
+template <int N> struct NdArrayDesc
+{
+ // The "extent" of each dimension. Indices along dimension d must be in the
+ // half-open interval [0, extents[d]).
+ int extents[N];
+
+ // The number of *elements* (not bytes) between consecutive indices of each
+ // dimension.
+ int strides[N];
+};
+
+// Copies dims to desc, calculating strides.
+template <int N>
+inline void copyDimsToDesc(const luci_interpreter::RuntimeShape &input_shape,
+ NdArrayDesc<N> *desc_out)
+{
+ int desc_stride = 1;
+ for (int i = N - 1; i >= 0; --i)
+ {
+ desc_out->extents[i] = input_shape.dims(i);
+ desc_out->strides[i] = desc_stride;
+ desc_stride *= input_shape.dims(i);
+ }
+}
+
+template <int N, int DIM, typename Calc>
+typename std::enable_if<DIM == N - 1, void>::type NDOpsHelperImpl(const NdArrayDesc<N> &output,
+ const Calc &calc, int indexes[N])
+{
+ for (indexes[DIM] = 0; indexes[DIM] < output.extents[DIM]; ++indexes[DIM])
+ {
+ calc(indexes);
+ }
+}
+
+template <int N, int DIM, typename Calc>
+typename std::enable_if<DIM != N - 1, void>::type NDOpsHelperImpl(const NdArrayDesc<N> &output,
+ const Calc &calc, int indexes[N])
+{
+ for (indexes[DIM] = 0; indexes[DIM] < output.extents[DIM]; ++indexes[DIM])
+ {
+ NDOpsHelperImpl<N, DIM + 1, Calc>(output, calc, indexes);
+ }
+}
+
+// Execute the calc function in the innermost iteration based on the shape of
+// the output. The calc function should take a single argument of type int[N].
+template <int N, typename Calc>
+inline void NDOpsHelper(const NdArrayDesc<N> &output, const Calc &calc)
+{
+ int indexes[N] = {0};
+ NDOpsHelperImpl<N, 0, Calc>(output, calc, indexes);
+}
+
+template <int N>
+inline void NdArrayDescsForElementwiseBroadcast(const luci_interpreter::RuntimeShape &input0_shape,
+ const luci_interpreter::RuntimeShape &input1_shape,
+ NdArrayDesc<N> *desc0_out,
+ NdArrayDesc<N> *desc1_out)
+{
+
+ auto extended_input0_shape = luci_interpreter::RuntimeShape::extendedShape(N, input0_shape);
+ auto extended_input1_shape = luci_interpreter::RuntimeShape::extendedShape(N, input1_shape);
+
+ // Copy dims to desc, calculating strides.
+ copyDimsToDesc<N>(extended_input0_shape, desc0_out);
+ copyDimsToDesc<N>(extended_input1_shape, desc1_out);
+
+ // Walk over each dimension. If the extents are equal do nothing.
+ // Otherwise, set the desc with extent 1 to have extent equal to the other and
+ // stride 0.
+ for (int i = 0; i < N; ++i)
+ {
+ const int extent0 = extended_input0_shape.dims(i);
+ const int extent1 = extended_input1_shape.dims(i);
+ if (extent0 != extent1)
+ {
+ if (extent0 == 1)
+ {
+ desc0_out->strides[i] = 0;
+ desc0_out->extents[i] = extent1;
+ }
+ else
+ {
+ desc1_out->strides[i] = 0;
+ desc1_out->extents[i] = extent0;
+ }
+ }
+ }
+}
+
+inline int subscriptToIndex(const NdArrayDesc<4> &desc, int i0, int i1, int i2, int i3)
+{
+ return i0 * desc.strides[0] + i1 * desc.strides[1] + i2 * desc.strides[2] + i3 * desc.strides[3];
+}
+
+inline int subscriptToIndex(const NdArrayDesc<5> &desc, int indexes[5])
+{
+ return indexes[0] * desc.strides[0] + indexes[1] * desc.strides[1] +
+ indexes[2] * desc.strides[2] + indexes[3] * desc.strides[3] + indexes[4] * desc.strides[4];
+}
+
+// Consolidates dimensions in broadcast inputs, checks for five-fold pattern.
+//
+// For example, if sequence of dimensions of one input is
+// ..., 1, 3, 1, 7, 9, 5,... and the other is ..., 2, 3, 1, 7, 1, 1, ...
+// we can consolidate these as
+// ..., 1, 3*7, 9*5, ... and 2, 3*7, 1.
+//
+// The category is updated in the less-frequent case of shapes that are
+// not suited to a fivefold-loop broadcast.
+//
+// Falls back to generic pattern when it does not know how to process properly.
+//
+// Returns true iff there is some sort of broadcast, which includes five-fold
+// patterns and falling back to generic broadcast.
+inline bool ProcessBroadcastShapes(const luci_interpreter::RuntimeShape &shape0,
+ const luci_interpreter::RuntimeShape &shape1,
+ luci_interpreter_pal::ArithmeticParams *params)
+{
+ const int dims_count = std::max(shape0.dimensionsCount(), shape1.dimensionsCount());
+
+ params->broadcast_category = BroadcastableOpCategory::kGenericBroadcast;
+
+ auto extended_shape0 = luci_interpreter::RuntimeShape::extendedShape(dims_count, shape0);
+ auto extended_shape1 = luci_interpreter::RuntimeShape::extendedShape(dims_count, shape1);
+
+ // Check for "exact" match, implicitly accepting any scalar shapes.
+ if (extended_shape0 == extended_shape1)
+ {
+ params->broadcast_category = BroadcastableOpCategory::kNonBroadcast;
+ return false;
+ }
+
+ if (shape0.flatSize() == 1)
+ {
+ params->broadcast_category = BroadcastableOpCategory::kScalarFirstBroadcast;
+ return true;
+ }
+ else if (shape1.flatSize() == 1)
+ {
+ params->broadcast_category = BroadcastableOpCategory::kScalarSecondBroadcast;
+ return true;
+ }
+
+ for (int i = dims_count - 1; i >= 0; --i)
+ {
+ if (extended_shape0.dims(i) == extended_shape1.dims(i))
+ {
+ continue;
+ }
+ else if (extended_shape0.dims(i) == 1)
+ {
+ params->broadcast_category = BroadcastableOpCategory::kFirstInputBroadcastsFast;
+ return true;
+ }
+ else if (extended_shape1.dims(i) == 1)
+ {
+ params->broadcast_category = BroadcastableOpCategory::kSecondInputBroadcastsFast;
+ return true;
+ }
+ else
+ {
+ // This case is erroneous: there is a dimension that does not match and
+ // is not a broadcast from one shape to the other.
+ params->broadcast_category = BroadcastableOpCategory::kGenericBroadcast;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_PROCESS_BROADCAST_SHAPES_H
diff --git a/onert-micro/luci-interpreter/pal/linux/KernelsToBuild.lst b/onert-micro/luci-interpreter/pal/linux/KernelsToBuild.lst
deleted file mode 100644
index 1f4ccb383..000000000
--- a/onert-micro/luci-interpreter/pal/linux/KernelsToBuild.lst
+++ /dev/null
@@ -1,77 +0,0 @@
-REGISTER_KERNEL(ADD, Add)
-REGISTER_KERNEL(ARG_MAX, ArgMax)
-REGISTER_KERNEL(AVERAGE_POOL_2D, AveragePool2D)
-REGISTER_KERNEL(BATCH_MATMUL, BatchMatMul)
-REGISTER_KERNEL(BATCH_TO_SPACE_ND, BatchToSpaceND)
-REGISTER_KERNEL(CAST, Cast)
-REGISTER_KERNEL(CONCATENATION, Concatenation)
-REGISTER_KERNEL(CONV_2D, Conv2D)
-REGISTER_KERNEL(DEPTH_TO_SPACE, DepthToSpace)
-REGISTER_KERNEL(DEPTHWISE_CONV_2D, DepthwiseConv2D)
-REGISTER_KERNEL(DEQUANTIZE, Dequantize)
-REGISTER_KERNEL(DIV, Div)
-REGISTER_KERNEL(ELU, Elu)
-REGISTER_KERNEL(EXP, Exp)
-REGISTER_KERNEL(EXPAND_DIMS, ExpandDims)
-REGISTER_KERNEL(FILL, Fill)
-REGISTER_KERNEL(FLOOR, Floor)
-REGISTER_KERNEL(FLOOR_DIV, FloorDiv)
-REGISTER_KERNEL(EQUAL, Equal)
-REGISTER_KERNEL(FULLY_CONNECTED, FullyConnected)
-REGISTER_KERNEL(GATHER, Gather)
-REGISTER_KERNEL(GREATER, Greater)
-REGISTER_KERNEL(GREATER_EQUAL, GreaterEqual)
-REGISTER_KERNEL(IF, If)
-REGISTER_KERNEL(INSTANCE_NORM, InstanceNorm)
-REGISTER_KERNEL(L2_NORMALIZATION, L2Normalize)
-REGISTER_KERNEL(L2_POOL_2D, L2Pool2D)
-REGISTER_KERNEL(LEAKY_RELU, LeakyRelu)
-REGISTER_KERNEL(LESS, Less)
-REGISTER_KERNEL(LESS_EQUAL, LessEqual)
-REGISTER_KERNEL(LOCAL_RESPONSE_NORMALIZATION, LocalResponseNormalization)
-REGISTER_KERNEL(LOGICAL_AND, LogicalAnd)
-REGISTER_KERNEL(LOGICAL_NOT, LogicalNot)
-REGISTER_KERNEL(LOGICAL_OR, LogicalOr)
-REGISTER_KERNEL(LOGISTIC, Logistic)
-REGISTER_KERNEL(LOG_SOFTMAX, LogSoftmax)
-REGISTER_KERNEL(MAXIMUM, Maximum)
-REGISTER_KERNEL(MAX_POOL_2D, MaxPool2D)
-REGISTER_KERNEL(MEAN, Mean)
-REGISTER_KERNEL(MINIMUM, Minimum)
-REGISTER_KERNEL(MIRROR_PAD, MirrorPad)
-REGISTER_KERNEL(MUL, Mul)
-REGISTER_KERNEL(NEG, Neg)
-REGISTER_KERNEL(NOT_EQUAL, NotEqual)
-REGISTER_KERNEL(ONE_HOT, OneHot)
-REGISTER_KERNEL(PACK, Pack)
-REGISTER_KERNEL(PAD, Pad)
-REGISTER_KERNEL(PADV2, PadV2)
-REGISTER_KERNEL(POW, Pow)
-REGISTER_KERNEL(PRELU, PRelu)
-REGISTER_KERNEL(QUANTIZE, Quantize)
-REGISTER_KERNEL(RELU, Relu)
-REGISTER_KERNEL(RELU6, Relu6)
-REGISTER_KERNEL(RESHAPE, Reshape)
-REGISTER_KERNEL(RESIZE_BILINEAR, ResizeBilinear)
-REGISTER_KERNEL(RESIZE_NEAREST_NEIGHBOR, ResizeNearestNeighbor)
-REGISTER_KERNEL(REVERSE_V2, ReverseV2)
-REGISTER_KERNEL(RSQRT, Rsqrt)
-REGISTER_KERNEL(SHAPE, Shape)
-REGISTER_KERNEL(SLICE, Slice)
-REGISTER_KERNEL(SOFTMAX, Softmax)
-REGISTER_KERNEL(SPACE_TO_BATCH_ND, SpaceToBatchND)
-REGISTER_KERNEL(SPACE_TO_DEPTH, SpaceToDepth)
-REGISTER_KERNEL(SPLIT, Split)
-REGISTER_KERNEL(SPLIT_V, SplitV)
-REGISTER_KERNEL(STRIDED_SLICE, StridedSlice)
-REGISTER_KERNEL(SQRT, Sqrt)
-REGISTER_KERNEL(SQUARE, Square)
-REGISTER_KERNEL(SQUARED_DIFFERENCE, SquaredDifference)
-REGISTER_KERNEL(SQUEEZE, Squeeze)
-REGISTER_KERNEL(SUB, Sub)
-REGISTER_KERNEL(SVDF, SVDF)
-REGISTER_KERNEL(TANH, Tanh)
-REGISTER_KERNEL(TRANSPOSE, Transpose)
-REGISTER_KERNEL(TRANSPOSE_CONV, TransposeConv)
-REGISTER_KERNEL(UNPACK, Unpack)
-REGISTER_KERNEL(WHILE, While)
diff --git a/onert-micro/luci-interpreter/pal/linux/PALArgMax.h b/onert-micro/luci-interpreter/pal/linux/PALArgMax.h
deleted file mode 100644
index 84147b205..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALArgMax.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_ARGMAX_H
-#define LUCI_INTERPRETER_PAL_ARGMAX_H
-
-#include <tensorflow/lite/kernels/internal/reference/arg_min_max.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T1, typename T2, typename T3>
-static inline void ArgMinMax(const tflite::RuntimeShape &input1_shape, const T1 *input1_data,
- const T2 *axis, const tflite::RuntimeShape &output_shape,
- T3 *output_data, const std::greater<T1> cmp)
-{
- tflite::reference_ops::ArgMinMax(input1_shape, input1_data, axis, output_shape, output_data, cmp);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_ARGMAX_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALAveragePool2d.h b/onert-micro/luci-interpreter/pal/linux/PALAveragePool2d.h
deleted file mode 100644
index fe93b67f0..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALAveragePool2d.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_AVERAGEPOOL2D_H
-#define LUCI_INTERPRETER_PAL_AVERAGEPOOL2D_H
-
-#include <tensorflow/lite/kernels/internal/reference/integer_ops/pooling.h>
-#include <tensorflow/lite/kernels/internal/reference/pooling.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void AveragePool(const tflite::PoolParams &params,
- const tflite::RuntimeShape &input_shape, const T *input_data,
- const tflite::RuntimeShape &output_shape, T *output_data,
- const tflite::RuntimeShape &scratchpad_shape, T *scratchpad_data)
-{
- {
- // MARK: At this moment this operation doesn't support
- assert(false && "AveragePool NYI");
- (void)params;
- (void)input_shape;
- (void)input_data;
- (void)output_shape;
- (void)output_data;
- (void)scratchpad_shape;
- (void)scratchpad_data;
- }
-}
-
-template <>
-inline void AveragePool<int8_t>(const tflite::PoolParams &params,
- const tflite::RuntimeShape &input_shape, const int8_t *input_data,
- const tflite::RuntimeShape &output_shape, int8_t *output_data,
- const tflite::RuntimeShape &scratchpad_shape,
- int8_t *scratchpad_data)
-{
- (void)scratchpad_shape;
- (void)scratchpad_data;
-
- tflite::reference_integer_ops::AveragePool(params, input_shape, input_data, output_shape,
- output_data);
-}
-
-static inline void SetupScratchpadTensor(luci_interpreter::Tensor *scratchpad,
- const luci_interpreter::DataType &input_data_type,
- const tflite::RuntimeShape &input_shape,
- const tflite::RuntimeShape &output_shape)
-
-{
- (void)input_data_type;
- (void)input_shape;
- (void)output_shape;
-
- scratchpad->set_allocatable(false);
-}
-
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_AVERAGEPOOL2D_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALBatchMatMul.h b/onert-micro/luci-interpreter/pal/linux/PALBatchMatMul.h
deleted file mode 100644
index a6f65641d..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALBatchMatMul.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_BATCHMATMUL_H
-#define LUCI_INTERPRETER_PAL_BATCHMATMUL_H
-
-#include <tensorflow/lite/kernels/internal/reference/batch_matmul.h>
-
-namespace luci_interpreter_pal
-{
-inline void BatchMatMul(const tflite::RuntimeShape &lhs_shape, const float *lhs_data,
- const tflite::RuntimeShape &rhs_shape, const float *rhs_data,
- const tflite::RuntimeShape &output_shape, float *output_data)
-{
- tflite::reference_ops::BatchMatMul(lhs_shape, lhs_data, rhs_shape, rhs_data, output_shape,
- output_data);
-}
-
-static inline void SetupScratchpadTensor(luci_interpreter::Tensor *lhs_scratchpad,
- luci_interpreter::Tensor *rhs_scratchpad,
- const tflite::RuntimeShape &lhs_shape,
- const tflite::RuntimeShape &rhs_shape)
-{
- // Scratchpad for transposed LHS
- {
- auto lhs_rank = lhs_shape.DimensionsCount();
- luci_interpreter::Shape scratchpad_size(lhs_rank);
- for (int i = 0; i < lhs_rank - 2; ++i)
- {
- scratchpad_size.dim(i) = lhs_shape.Dims(i);
- }
- scratchpad_size.dim(lhs_rank - 2) = lhs_shape.Dims(lhs_rank - 1);
- scratchpad_size.dim(lhs_rank - 1) = lhs_shape.Dims(lhs_rank - 2);
-
- lhs_scratchpad->resize(scratchpad_size);
- }
- // Scratchpad for transposed RHS
- {
- auto rhs_rank = rhs_shape.DimensionsCount();
- luci_interpreter::Shape scratchpad_size(rhs_rank);
- for (int i = 0; i < rhs_rank - 2; ++i)
- {
- scratchpad_size.dim(i) = rhs_shape.Dims(i);
- }
- scratchpad_size.dim(rhs_rank - 2) = rhs_shape.Dims(rhs_rank - 1);
- scratchpad_size.dim(rhs_rank - 1) = rhs_shape.Dims(rhs_rank - 2);
-
- rhs_scratchpad->resize(scratchpad_size);
- }
-}
-
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_BATCHMATMUL_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALBatchToSpaceND.h b/onert-micro/luci-interpreter/pal/linux/PALBatchToSpaceND.h
deleted file mode 100644
index 52da2a8f3..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALBatchToSpaceND.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_BATCHTOSPACEND_H
-#define LUCI_INTERPRETER_PAL_BATCHTOSPACEND_H
-
-#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void
-BatchToSpaceND(const tflite::RuntimeShape &unextended_input1_shape, const T *input1_data,
- const tflite::RuntimeShape &unextended_input2_shape, const int32 *block_shape_data,
- const tflite::RuntimeShape &unextended_input3_shape, const int32 *crops_data,
- const tflite::RuntimeShape &unextended_output_shape, T *output_data)
-{
- tflite::optimized_ops::BatchToSpaceND(
- unextended_input1_shape, input1_data, unextended_input2_shape, block_shape_data,
- unextended_input3_shape, crops_data, unextended_output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_BATCHTOSPACEND_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALConv2d.h b/onert-micro/luci-interpreter/pal/linux/PALConv2d.h
deleted file mode 100644
index 1c2658679..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALConv2d.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_CONV2D_H
-#define LUCI_INTERPRETER_PAL_CONV2D_H
-
-#include <tensorflow/lite/kernels/internal/optimized/legacy_optimized_ops.h>
-#include <tensorflow/lite/kernels/internal/reference/integer_ops/conv.h>
-
-namespace luci_interpreter_pal
-{
-static inline void Conv(const tflite::ConvParams &params, const tflite::RuntimeShape &input_shape,
- const float *input_data, const tflite::RuntimeShape &filter_shape,
- const float *filter_data, const tflite::RuntimeShape &bias_shape,
- const float *bias_data, const tflite::RuntimeShape &output_shape,
- float *output_data, const tflite::RuntimeShape &scratchpad_shape,
- float *scratchpad_data)
-{
- (void)scratchpad_shape;
- if (scratchpad_data)
- {
- const int32_t batches = tflite::MatchingDim(input_shape, 0, output_shape, 0);
- const int32_t input_depth = tflite::MatchingDim(input_shape, 3, filter_shape, 3);
- const int32_t output_height = output_shape.Dims(1);
- const int32_t output_width = output_shape.Dims(2);
- const int32_t filter_height = filter_shape.Dims(1);
- const int32_t filter_width = filter_shape.Dims(2);
- tflite::RuntimeShape im2col_shape{batches, output_height, output_width,
- input_depth * filter_height * filter_width};
-
- tflite::optimized_ops::Conv(params, input_shape, input_data, filter_shape, filter_data,
- bias_shape, bias_data, output_shape, output_data, im2col_shape,
- scratchpad_data);
- }
- else
- tflite::reference_ops::Conv(params, input_shape, input_data, filter_shape, filter_data,
- bias_shape, bias_data, output_shape, output_data,
- tflite::RuntimeShape(), nullptr);
-}
-
-static inline void Conv(const tflite::ConvParams &params, const tflite::RuntimeShape &input_shape,
- const uint8 *input_data, const tflite::RuntimeShape &filter_shape,
- const uint8 *filter_data, const tflite::RuntimeShape &bias_shape,
- const int32 *bias_data, const tflite::RuntimeShape &output_shape,
- uint8 *output_data, const tflite::RuntimeShape &scratchpad_shape,
- uint8 *scratchpad_data)
-{
- // TODO This should only be done once (although it takes only a few microseconds).
- // Also, the user should be able to adjust the number of threads.
- auto gemmlowp_context = std::make_unique<gemmlowp::GemmContext>();
- gemmlowp_context->set_max_num_threads(static_cast<int>(std::thread::hardware_concurrency()));
-
- tflite::reference_ops::Conv(params, input_shape, input_data, filter_shape, filter_data,
- bias_shape, bias_data, output_shape, output_data, scratchpad_shape,
- scratchpad_data, gemmlowp_context.get());
-}
-
-static inline void ConvPerChannel(const tflite::ConvParams &params, const int32_t *mult,
- const int32_t *shifts, const tflite::RuntimeShape &input_shape,
- const int8 *input_data, const tflite::RuntimeShape &filter_shape,
- const int8 *filter_data, const tflite::RuntimeShape &bias_shape,
- const int32 *bias_data, const tflite::RuntimeShape &output_shape,
- int8 *output_data, const tflite::RuntimeShape &scratchpad_shape,
- int8 *scratchpad_data)
-{
- (void)scratchpad_shape;
- (void)scratchpad_data;
- // TODO enable optimized version
- tflite::reference_integer_ops::ConvPerChannel(params, mult, shifts, input_shape, input_data,
- filter_shape, filter_data, bias_shape, bias_data,
- output_shape, output_data);
-}
-
-static inline void SetupScratchpadTensor(luci_interpreter::Tensor *scratchpad,
- const luci_interpreter::DataType &input_data_type,
- const tflite::ConvParams &params,
- const tflite::RuntimeShape &input_shape,
- const tflite::RuntimeShape &filter_shape,
- const tflite::RuntimeShape &output_shape)
-{
- const int32_t filter_height = filter_shape.Dims(1);
- const int32_t filter_width = filter_shape.Dims(2);
-
- // Allocate tensor for scratchpad, if needed.
- // The checks here should be aligned with the actual implementation.
- const bool need_dilated_scratchpad =
- params.dilation_height_factor != 1 || params.dilation_width_factor != 1;
- const bool need_non_dilated_scratchpad = params.stride_height != 1 || params.stride_width != 1 ||
- filter_height != 1 || filter_width != 1;
- auto _need_scratchpad = input_data_type != luci_interpreter::DataType::S16 &&
- (need_dilated_scratchpad || need_non_dilated_scratchpad);
-
- if (_need_scratchpad)
- {
- const int32_t batches = tflite::MatchingDim(input_shape, 0, output_shape, 0);
- const int32_t input_depth = tflite::MatchingDim(input_shape, 3, filter_shape, 3);
- const int32_t output_height = output_shape.Dims(1);
- const int32_t output_width = output_shape.Dims(2);
-
- auto data_type_size = static_cast<int32_t>(luci_interpreter::getDataTypeSize(input_data_type));
- int32_t scratchpad_size = batches * output_width * output_height * input_depth * filter_height *
- filter_width * data_type_size;
- luci_interpreter::Shape scratchpad_shape{scratchpad_size};
- scratchpad->resize(scratchpad_shape);
- }
- else
- {
- scratchpad->set_allocatable(false);
- }
-}
-
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_CONV2D_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALDepthToSpace.h b/onert-micro/luci-interpreter/pal/linux/PALDepthToSpace.h
deleted file mode 100644
index 6372e4eb6..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALDepthToSpace.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_DEPTHTOSPACE_H
-#define LUCI_INTERPRETER_PAL_DEPTHTOSPACE_H
-
-#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void DepthToSpace(const tflite::DepthToSpaceParams &op_params,
- const tflite::RuntimeShape &unextended_input_shape,
- const T *input_data,
- const tflite::RuntimeShape &unextended_output_shape, T *output_data)
-{
- tflite::optimized_ops::DepthToSpace(op_params, unextended_input_shape, input_data,
- unextended_output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_DEPTHTOSPACE_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALDepthwiseConv2d.h b/onert-micro/luci-interpreter/pal/linux/PALDepthwiseConv2d.h
deleted file mode 100644
index 1cba99652..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALDepthwiseConv2d.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_DEPTHWISECONV2D_H
-#define LUCI_INTERPRETER_PAL_DEPTHWISECONV2D_H
-
-#include <tensorflow/lite/kernels/internal/reference/depthwiseconv_float.h>
-#include <tensorflow/lite/kernels/internal/reference/depthwiseconv_uint8.h>
-#include <tensorflow/lite/kernels/internal/reference/integer_ops/depthwise_conv.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void
-DepthwiseConvPerChannel(const tflite::DepthwiseParams &params, const int32_t *output_multiplier,
- const int32_t *output_shift, const tflite::RuntimeShape &input_shape,
- const T *input_data, const tflite::RuntimeShape &filter_shape,
- const T *filter_data, const tflite::RuntimeShape &bias_shape,
- const int32_t *bias_data, const tflite::RuntimeShape &output_shape,
- T *output_data, const tflite::RuntimeShape &scratchpad_shape,
- T *scratchpad_data)
-{
- {
- // MARK: At this moment this operation is not supported
- assert(false && "DepthwiseConvPerChannel NYI");
- (void)params;
- (void)output_multiplier;
- (void)output_shift;
- (void)input_shape;
- (void)output_data;
- (void)input_data;
- (void)filter_shape;
- (void)filter_data;
- (void)bias_shape;
- (void)bias_data;
- (void)output_shape;
- (void)output_data;
- (void)scratchpad_shape;
- (void)scratchpad_data;
- }
-}
-
-template <>
-inline void DepthwiseConvPerChannel<int8_t>(
- const tflite::DepthwiseParams &params, const int32_t *output_multiplier,
- const int32_t *output_shift, const tflite::RuntimeShape &input_shape, const int8_t *input_data,
- const tflite::RuntimeShape &filter_shape, const int8_t *filter_data,
- const tflite::RuntimeShape &bias_shape, const int32_t *bias_data,
- const tflite::RuntimeShape &output_shape, int8_t *output_data,
- const tflite::RuntimeShape &scratchpad_shape, int8_t *scratchpad_data)
-{
- (void)scratchpad_shape;
- (void)scratchpad_data;
- tflite::reference_integer_ops::DepthwiseConvPerChannel(
- params, output_multiplier, output_shift, input_shape, input_data, filter_shape, filter_data,
- bias_shape, bias_data, output_shape, output_data);
-}
-
-static inline void SetupScratchpadTensor(luci_interpreter::Tensor *scratchpad,
- const tflite::DepthwiseParams &params,
- const luci_interpreter::DataType &input_data_type,
- const tflite::RuntimeShape &input_shape,
- const tflite::RuntimeShape &filter_shape,
- const tflite::RuntimeShape &output_shape)
-
-{
- (void)params;
- (void)input_data_type;
- (void)input_shape;
- (void)filter_shape;
- (void)output_shape;
-
- scratchpad->set_allocatable(false);
-}
-
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_DEPTHWISECONV2D_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALDequantize.h b/onert-micro/luci-interpreter/pal/linux/PALDequantize.h
deleted file mode 100644
index b505129f1..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALDequantize.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_DEQUANTIZE_H
-#define LUCI_INTERPRETER_PAL_DEQUANTIZE_H
-
-#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void Dequantize(tflite::DequantizationParams &params,
- const tflite::RuntimeShape &input_shape, const T *input_data,
- const tflite::RuntimeShape &output_shape, float *output_data)
-{
- tflite::optimized_ops::Dequantize(params, input_shape, input_data, output_shape, output_data);
-}
-
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_DEQUANTIZE_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALFullyConnected.h b/onert-micro/luci-interpreter/pal/linux/PALFullyConnected.h
deleted file mode 100644
index ed8d2a68f..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALFullyConnected.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_FULLYCONNECTED_H
-#define LUCI_INTERPRETER_PAL_FULLYCONNECTED_H
-
-#include <tensorflow/lite/kernels/internal/reference/fully_connected.h>
-#include <tensorflow/lite/kernels/internal/reference/integer_ops/fully_connected.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void FullyConnected(const tflite::FullyConnectedParams &params,
- const tflite::RuntimeShape &input_shape, const T *input_data,
- const tflite::RuntimeShape &filter_shape, const T *filter_data,
- const tflite::RuntimeShape &bias_shape, const int32_t *bias_data,
- const tflite::RuntimeShape &output_shape, T *output_data)
-{
- {
- // MARK: At this moment this operation doesn't support
- assert(false && "FullyConnected NYI");
- (void)params;
- (void)input_shape;
- (void)input_data;
- (void)filter_shape;
- (void)filter_data;
- (void)bias_shape;
- (void)bias_data;
- (void)output_shape;
- (void)output_data;
- }
-}
-
-template <>
-inline void
-FullyConnected<int8_t>(const tflite::FullyConnectedParams &params,
- const tflite::RuntimeShape &input_shape, const int8_t *input_data,
- const tflite::RuntimeShape &filter_shape, const int8_t *filter_data,
- const tflite::RuntimeShape &bias_shape, const int32_t *bias_data,
- const tflite::RuntimeShape &output_shape, int8_t *output_data)
-{
- tflite::reference_integer_ops::FullyConnected(params, input_shape, input_data, filter_shape,
- filter_data, bias_shape, bias_data, output_shape,
- output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_FULLYCONNECTED_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALGather.h b/onert-micro/luci-interpreter/pal/linux/PALGather.h
deleted file mode 100644
index 97d5431ce..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALGather.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_GATHER_H
-#define LUCI_INTERPRETER_PAL_GATHER_H
-
-#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T, typename CoordsT = int32>
-static inline void Gather(const tflite::GatherParams &op_params,
- const tflite::RuntimeShape &input_shape, const T *input_data,
- const tflite::RuntimeShape &coords_shape, const CoordsT *coords_data,
- const tflite::RuntimeShape &output_shape, T *output_data)
-{
- tflite::optimized_ops::Gather(op_params, input_shape, input_data, coords_shape, coords_data,
- output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_GATHER_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALL2Normalize.h b/onert-micro/luci-interpreter/pal/linux/PALL2Normalize.h
deleted file mode 100644
index 5d2c09f9e..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALL2Normalize.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_L2NORMALIZE_H
-#define LUCI_INTERPRETER_PAL_L2NORMALIZE_H
-
-#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void L2Normalization(const tflite::L2NormalizationParams &op_params,
- const tflite::RuntimeShape &input_shape, const T *input_data,
- const tflite::RuntimeShape &output_shape, T *output_data)
-{
- tflite::optimized_ops::L2Normalization(op_params, input_shape, input_data, output_shape,
- output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_L2NORMALIZE_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALL2Pool2D.h b/onert-micro/luci-interpreter/pal/linux/PALL2Pool2D.h
deleted file mode 100644
index 121ced91e..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALL2Pool2D.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_L2POOL2D_H
-#define LUCI_INTERPRETER_PAL_L2POOL2D_H
-
-#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void L2Pool(const tflite::PoolParams &params, const tflite::RuntimeShape &input_shape,
- const T *input_data, const tflite::RuntimeShape &output_shape,
- T *output_data)
-{
- tflite::optimized_ops::L2Pool(params, input_shape, input_data, output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_L2POOL2D_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALLocalResponseNormalization.h b/onert-micro/luci-interpreter/pal/linux/PALLocalResponseNormalization.h
deleted file mode 100644
index b99665006..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALLocalResponseNormalization.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_LOCALRESPONSENORMALIZATION_H
-#define LUCI_INTERPRETER_PAL_LOCALRESPONSENORMALIZATION_H
-
-#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
-
-namespace luci_interpreter_pal
-{
-static inline void
-LocalResponseNormalization(const tflite::LocalResponseNormalizationParams &op_params,
- const tflite::RuntimeShape &input_shape, const float *input_data,
- const tflite::RuntimeShape &output_shape, float *output_data)
-{
- tflite::optimized_ops::LocalResponseNormalization(op_params, input_shape, input_data,
- output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_LOCALRESPONSENORMALIZATION_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALLogSoftmax.h b/onert-micro/luci-interpreter/pal/linux/PALLogSoftmax.h
deleted file mode 100644
index 099b2d20a..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALLogSoftmax.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_LOGSOFTMAX_H
-#define LUCI_INTERPRETER_PAL_LOGSOFTMAX_H
-
-#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
-
-namespace luci_interpreter_pal
-{
-static inline void PopulateSoftmaxLookupTable(tflite::SoftmaxParams *data, float input_scale,
- float beta)
-{
- tflite::optimized_ops::PopulateSoftmaxLookupTable(data, input_scale, beta);
-}
-
-static inline void InitializeParams(tflite::SoftmaxParams *params, float input_scale, float beta)
-{
- // Do nothing for linux
- (void)params;
- (void)input_scale;
- (void)beta;
-}
-
-static inline void LogSoftmax(const tflite::SoftmaxParams &params, float input_scale,
- const tflite::RuntimeShape &input_shape, const uint8 *input_data,
- const tflite::RuntimeShape &output_shape, uint8 *output_data)
-{
- tflite::optimized_ops::LogSoftmax(params, input_scale, input_shape, input_data, output_shape,
- output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_LOGSOFTMAX_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALMul.h b/onert-micro/luci-interpreter/pal/linux/PALMul.h
deleted file mode 100644
index d2a4d1f0f..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALMul.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_MUL_H
-#define LUCI_INTERPRETER_PAL_MUL_H
-
-#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void Mul(tflite::ArithmeticParams &params, const tflite::RuntimeShape &input1_shape,
- const T *input1_data, const tflite::RuntimeShape &input2_shape,
- const T *input2_data, const tflite::RuntimeShape &output_shape,
- T *output_data)
-{
- tflite::optimized_ops::Mul(params, input1_shape, input1_data, input2_shape, input2_data,
- output_shape, output_data);
-}
-
-template <>
-inline void Mul(tflite::ArithmeticParams &params, const tflite::RuntimeShape &input1_shape,
- const int64_t *input1_data, const tflite::RuntimeShape &input2_shape,
- const int64_t *input2_data, const tflite::RuntimeShape &output_shape,
- int64_t *output_data)
-{
- tflite::optimized_ops::BroadcastMul4DSlow(params, input1_shape, input1_data, input2_shape,
- input2_data, output_shape, output_data);
-}
-
-template <typename T>
-static inline void
-BroadcastMul4DSlow(tflite::ArithmeticParams &params, const tflite::RuntimeShape &input1_shape,
- const T *input1_data, const tflite::RuntimeShape &input2_shape,
- const T *input2_data, const tflite::RuntimeShape &output_shape, T *output_data)
-{
- tflite::optimized_ops::BroadcastMul4DSlow(params, input1_shape, input1_data, input2_shape,
- input2_data, output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_MUL_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALQuantize.h b/onert-micro/luci-interpreter/pal/linux/PALQuantize.h
deleted file mode 100644
index ebaf876bf..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALQuantize.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_QUANTIZE_H
-#define LUCI_INTERPRETER_PAL_QUANTIZE_H
-
-#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void Quantize(tflite::QuantizationParams &params,
- const tflite::RuntimeShape &input_shape, const float *input_data,
- const tflite::RuntimeShape &output_shape, T *output_data)
-{
- tflite::optimized_ops::AffineQuantize(params, input_shape, input_data, output_shape, output_data);
-}
-
-template <typename Input, typename Output>
-static inline void Requantize(const Input *input_data, int32_t size,
- int32_t effective_scale_multiplier, int32_t effective_scale_shift,
- int32_t input_zero_point, int32_t output_zero_point,
- Output *output_data)
-{
- tflite::optimized_ops::Requantize(input_data, size, effective_scale_multiplier,
- effective_scale_shift, input_zero_point, output_zero_point,
- output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_QUANTIZE_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALRelu.h b/onert-micro/luci-interpreter/pal/linux/PALRelu.h
deleted file mode 100644
index de17750e6..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALRelu.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_RELU_H
-#define LUCI_INTERPRETER_PAL_RELU_H
-
-#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
-
-namespace luci_interpreter_pal
-{
-static inline void Relu(const tflite::RuntimeShape &input_shape, const float *input_data,
- const tflite::RuntimeShape &output_shape, float *output_data)
-{
- tflite::optimized_ops::Relu(input_shape, input_data, output_shape, output_data);
-}
-
-template <typename T>
-static inline void ReluX(const tflite::ReluParams &params, const tflite::RuntimeShape &input_shape,
- const T *input_data, const tflite::RuntimeShape &output_shape,
- T *output_data)
-{
- tflite::optimized_ops::ReluX(params, input_shape, input_data, output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_RELU_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALRelu6.h b/onert-micro/luci-interpreter/pal/linux/PALRelu6.h
deleted file mode 100644
index e546a2c7e..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALRelu6.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_RELU6_H
-#define LUCI_INTERPRETER_PAL_RELU6_H
-
-#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
-
-namespace luci_interpreter_pal
-{
-static inline void Relu6(const tflite::RuntimeShape &input_shape, const float *input_data,
- const tflite::RuntimeShape &output_shape, float *output_data)
-{
- tflite::optimized_ops::Relu6(input_shape, input_data, output_shape, output_data);
-}
-
-template <typename T>
-static inline void ReluX(const tflite::ReluParams &params, const tflite::RuntimeShape &input_shape,
- const T *input_data, const tflite::RuntimeShape &output_shape,
- T *output_data)
-{
- tflite::optimized_ops::ReluX(params, input_shape, input_data, output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_RELU6_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALResizeBilinear.h b/onert-micro/luci-interpreter/pal/linux/PALResizeBilinear.h
deleted file mode 100644
index 0ccfa0497..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALResizeBilinear.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_RESIZEBILINEAR_H
-#define LUCI_INTERPRETER_PAL_RESIZEBILINEAR_H
-
-#include <tensorflow/lite/kernels/internal/optimized/resize_bilinear.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void
-ResizeBilinear(const tflite::ResizeBilinearParams &op_params,
- const tflite::RuntimeShape &unextended_input_shape, const T *input_data,
- const tflite::RuntimeShape &output_size_shape, const int32 *output_size_data,
- const tflite::RuntimeShape &unextended_output_shape, T *output_data)
-{
- tflite::optimized_ops::ResizeBilinear(op_params, unextended_input_shape, input_data,
- output_size_shape, output_size_data,
- unextended_output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_RESIZEBILINEAR_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALResizeNearestNeighbor.h b/onert-micro/luci-interpreter/pal/linux/PALResizeNearestNeighbor.h
deleted file mode 100644
index c5006119b..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALResizeNearestNeighbor.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_RESIZENEARESTNEIGHBOR_H
-#define LUCI_INTERPRETER_PAL_RESIZENEARESTNEIGHBOR_H
-
-#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void
-ResizeNearestNeighbor(const tflite::ResizeNearestNeighborParams &op_params,
- const tflite::RuntimeShape &unextended_input_shape, const T *input_data,
- const tflite::RuntimeShape &output_size_shape, const int32 *output_size_data,
- const tflite::RuntimeShape &unextended_output_shape, T *output_data)
-{
- tflite::optimized_ops::ResizeNearestNeighbor(op_params, unextended_input_shape, input_data,
- output_size_shape, output_size_data,
- unextended_output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_RESIZENEARESTNEIGHBOR_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALSVDF.h b/onert-micro/luci-interpreter/pal/linux/PALSVDF.h
deleted file mode 100644
index 438c63dde..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALSVDF.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_SVDF_H
-#define LUCI_INTERPRETER_PAL_SVDF_H
-
-#include <tensorflow/lite/kernels/internal/reference/svdf.h>
-
-namespace luci_interpreter_pal
-{
-static inline void
-IntegerSVDF(const TfLiteSVDFParams &params, const tflite::RuntimeShape &input_shape,
- const int8_t *input_data, const tflite::RuntimeShape &weight_feature_shape,
- const int8_t *weight_feature_data, const tflite::RuntimeShape &weight_time_shape,
- const int16_t *weight_time_data, const tflite::RuntimeShape &bias_shape,
- const int32_t *bias_data, int16_t *activation_state_data,
- const tflite::RuntimeShape &output_shape, int8_t *output_data, int32_t *scratchpad_data,
- int32_t *output_temp_data, int32_t scale_1_a, int scale_1_b, int32_t scale_2_a,
- int scale_2_b, int32_t input_zp, int32_t output_zp)
-{
- tflite::reference_ops::EvalIntegerSVDF(&params, input_shape, input_data, weight_feature_shape,
- weight_feature_data, weight_time_shape, weight_time_data,
- bias_shape, bias_data, activation_state_data, output_shape,
- output_data, scratchpad_data, output_temp_data, scale_1_a,
- scale_1_b, scale_2_a, scale_2_b, input_zp, output_zp);
-}
-static inline void
-FloatSVDF(const TfLiteSVDFParams &params, const tflite::RuntimeShape &input_shape,
- const float *input_data, const tflite::RuntimeShape &weight_feature_shape,
- const float *weight_feature_data, const tflite::RuntimeShape &weight_time_shape,
- const float *weight_time_data, const tflite::RuntimeShape &bias_shape,
- const float *bias_data, float *scratchpad_data, float *activation_state_data,
- const tflite::RuntimeShape &output_shape, float *output_data)
-{
- tflite::reference_ops::EvalFloatSVDF(&params, input_shape, input_data, weight_feature_shape,
- weight_feature_data, weight_time_shape, weight_time_data,
- bias_shape, bias_data, scratchpad_data,
- activation_state_data, output_shape, output_data);
-}
-
-static inline void SetupScratchpadTensor(
- const luci_interpreter::DataType &input_data_type,
- const luci_interpreter::DataType &weight_feature_data_type,
- luci_interpreter::Tensor *scratchpad_1, luci_interpreter::Tensor *scratchpad_2,
- luci_interpreter::Tensor *scratchpad_3, luci_interpreter::Tensor *scratchpad_4,
- luci_interpreter::Tensor *scratchpad_5, luci_interpreter::Tensor *scratchpad_6,
- const luci_interpreter::Shape input_shape, const luci_interpreter::Shape weight_time_shape,
- const int32_t batch_size, const int32_t num_filters, const int32_t num_units)
-{
-
- if (input_data_type == luci_interpreter::DataType::FLOAT32 &&
- (weight_feature_data_type == luci_interpreter::DataType::S8 ||
- weight_feature_data_type == luci_interpreter::DataType::U8))
- {
- (void)input_shape;
- (void)weight_time_shape;
- (void)scratchpad_3;
- (void)scratchpad_4;
- (void)scratchpad_5;
- (void)scratchpad_6;
-
- assert(false && "Hybrid type is not currently supported for linux platform");
- }
-
- // Resize scratchpad_1 tensor
- scratchpad_1->resize({batch_size, num_filters});
-
- if (input_data_type == luci_interpreter::DataType::S8)
- {
- // Resize scratchpad_2 for full_integer op
- scratchpad_2->resize({batch_size, num_units});
- }
-}
-
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_SVDF_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALSlice.h b/onert-micro/luci-interpreter/pal/linux/PALSlice.h
deleted file mode 100644
index 0984bf7f4..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALSlice.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_SLICE_H
-#define LUCI_INTERPRETER_PAL_SLICE_H
-
-#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void Slice(const tflite::SliceParams &op_params,
- const tflite::RuntimeShape &input_shape, const T *input_data,
- const tflite::RuntimeShape &output_shape, T *output_data)
-{
- tflite::optimized_ops::Slice(op_params, input_shape, input_data, output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_SLICE_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALSoftmax.h b/onert-micro/luci-interpreter/pal/linux/PALSoftmax.h
deleted file mode 100644
index abd38a573..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALSoftmax.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_SOFTMAX_H
-#define LUCI_INTERPRETER_PAL_SOFTMAX_H
-
-#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
-
-namespace luci_interpreter_pal
-{
-static inline void PopulateSoftmaxLookupTable(tflite::SoftmaxParams *data, float input_scale,
- float beta)
-{
- tflite::optimized_ops::PopulateSoftmaxLookupTable(data, input_scale, beta);
-}
-
-static inline void InitializeParams(tflite::SoftmaxParams *params, float input_scale, float beta)
-{
- // Do nothing for linux
- (void)params;
- (void)input_scale;
- (void)beta;
-}
-
-template <typename In, typename Out>
-static inline void Softmax(const tflite::SoftmaxParams &params,
- const tflite::RuntimeShape &input_shape, const In *input_data,
- const tflite::RuntimeShape &output_shape, Out *output_data)
-{
- tflite::optimized_ops::Softmax(params, input_shape, input_data, output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_SOFTMAX_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALSpaceToBatchND.h b/onert-micro/luci-interpreter/pal/linux/PALSpaceToBatchND.h
deleted file mode 100644
index 72757991e..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALSpaceToBatchND.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_SPACETOBATCHND_H
-#define LUCI_INTERPRETER_PAL_SPACETOBATCHND_H
-
-#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void
-SpaceToBatchND(const tflite::SpaceToBatchParams &params,
- const tflite::RuntimeShape &unextended_input1_shape, const T *input1_data,
- const tflite::RuntimeShape &unextended_input2_shape, const int32 *block_shape_data,
- const tflite::RuntimeShape &unextended_input3_shape, const int32 *paddings_data,
- const tflite::RuntimeShape &unextended_output_shape, T *output_data)
-{
- tflite::optimized_ops::SpaceToBatchND(
- params, unextended_input1_shape, input1_data, unextended_input2_shape, block_shape_data,
- unextended_input3_shape, paddings_data, unextended_output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_SPACETOBATCHND_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALSpaceToDepth.h b/onert-micro/luci-interpreter/pal/linux/PALSpaceToDepth.h
deleted file mode 100644
index 3013fc1bd..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALSpaceToDepth.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_SPACETODEPTH_H
-#define LUCI_INTERPRETER_PAL_SPACETODEPTH_H
-
-#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void SpaceToDepth(const tflite::SpaceToDepthParams &op_params,
- const tflite::RuntimeShape &unextended_input_shape,
- const T *input_data,
- const tflite::RuntimeShape &unextended_output_shape, T *output_data)
-{
- tflite::optimized_ops::SpaceToDepth(op_params, unextended_input_shape, input_data,
- unextended_output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_SPACETODEPTH_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALSplit.h b/onert-micro/luci-interpreter/pal/linux/PALSplit.h
deleted file mode 100644
index dad048fbf..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALSplit.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_SPLIT_H
-#define LUCI_INTERPRETER_PAL_SPLIT_H
-
-#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
-
-namespace luci_interpreter_pal
-{
-template <typename Scalar>
-static inline void Split(const tflite::SplitParams &params, const tflite::RuntimeShape &input_shape,
- const Scalar *input_data, const tflite::RuntimeShape *const *output_shapes,
- Scalar *const *output_data)
-{
- tflite::optimized_ops::Split(params, input_shape, input_data, output_shapes, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_SPLIT_H
diff --git a/onert-micro/luci-interpreter/pal/linux/PALSub.h b/onert-micro/luci-interpreter/pal/linux/PALSub.h
deleted file mode 100644
index 1babe1abd..000000000
--- a/onert-micro/luci-interpreter/pal/linux/PALSub.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_SUB_H
-#define LUCI_INTERPRETER_PAL_SUB_H
-
-#include <tensorflow/lite/kernels/internal/optimized/legacy_optimized_ops.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void Sub(const tflite::ArithmeticParams &params,
- const tflite::RuntimeShape &input1_shape, const T *input1_data,
- const tflite::RuntimeShape &input2_shape, const T *input2_data,
- const tflite::RuntimeShape &output_shape, T *output_data)
-{
- tflite::optimized_ops::Sub(params, input1_shape, input1_data, input2_shape, input2_data,
- output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_SUB_H
diff --git a/onert-micro/luci-interpreter/pal/linux/pal.cmake b/onert-micro/luci-interpreter/pal/linux/pal.cmake
deleted file mode 100644
index c373b9641..000000000
--- a/onert-micro/luci-interpreter/pal/linux/pal.cmake
+++ /dev/null
@@ -1,82 +0,0 @@
-macro(initialize_pal)
- nnas_find_package(TensorFlowSource EXACT 2.6.0 QUIET)
- nnas_find_package(TensorFlowGEMMLowpSource EXACT 2.6.0 QUIET)
- nnas_find_package(TensorFlowEigenSource EXACT 2.6.0 QUIET)
- nnas_find_package(TensorFlowRuySource EXACT 2.6.0 QUIET)
-
- if (NOT TensorFlowSource_FOUND)
- message(STATUS "Skipping luci-interpreter: TensorFlow not found")
- return()
- endif ()
-
- if (NOT TensorFlowGEMMLowpSource_FOUND)
- message(STATUS "Skipping luci-interpreter: gemmlowp not found")
- return()
- endif ()
-
- if (NOT TensorFlowEigenSource_FOUND)
- message(STATUS "Skipping luci-interpreter: Eigen not found")
- return()
- endif ()
-
- if (NOT TensorFlowRuySource_FOUND)
- message(STATUS "Skipping luci-interpreter: Ruy not found")
- return()
- endif ()
-
- find_package(Threads REQUIRED)
-
- set(PAL_INITIALIZED TRUE)
-endmacro()
-
-macro(add_pal_to_target TGT)
- target_include_directories(${TGT} PRIVATE "${PAL}")
- target_include_directories(${TGT} SYSTEM PRIVATE
- "${TensorFlowRuySource_DIR}"
- "${TensorFlowGEMMLowpSource_DIR}"
- "${TensorFlowEigenSource_DIR}"
- "${TensorFlowSource_DIR}")
- target_include_directories(${TGT} PRIVATE ${LUCI_INTERPRETER_PAL_DIR})
-
- # TODO put it back, I changed my mind.
- # instead add sources with visitors in this library
- set(PAL_SOURCES ${TensorFlowSource_DIR}/tensorflow/lite/kernels/internal/tensor_utils.cc
- ${TensorFlowSource_DIR}/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.cc
- ${TensorFlowSource_DIR}/tensorflow/lite/kernels/internal/quantization_util.cc)
-
- if(BUILD_ARM32_NEON)
- # NOTE may need to revise this list for version upgrade
- set(PAL_SOURCES ${PAL_SOURCES}
- ${TensorFlowSource_DIR}/tensorflow/lite/kernels/internal/optimized/neon_tensor_utils.cc
- ${TensorFlowSource_DIR}/tensorflow/lite/kernels/internal/optimized/cpu_check.cc
- ${TensorFlowRuySource_DIR}/ruy/allocator.cc
- ${TensorFlowRuySource_DIR}/ruy/block_map.cc
- ${TensorFlowRuySource_DIR}/ruy/blocking_counter.cc
- ${TensorFlowRuySource_DIR}/ruy/context_get_ctx.cc
- ${TensorFlowRuySource_DIR}/ruy/cpuinfo.cc
- ${TensorFlowRuySource_DIR}/ruy/ctx.cc
- ${TensorFlowRuySource_DIR}/ruy/denormal.cc
- ${TensorFlowRuySource_DIR}/ruy/frontend.cc
- ${TensorFlowRuySource_DIR}/ruy/pack_arm.cc
- ${TensorFlowRuySource_DIR}/ruy/prepacked_cache.cc
- ${TensorFlowRuySource_DIR}/ruy/prepare_packed_matrices.cc
- ${TensorFlowRuySource_DIR}/ruy/system_aligned_alloc.cc
- ${TensorFlowRuySource_DIR}/ruy/thread_pool.cc
- ${TensorFlowRuySource_DIR}/ruy/trmul.cc
- ${TensorFlowRuySource_DIR}/ruy/tune.cc
- ${TensorFlowRuySource_DIR}/ruy/wait.cc
- ${TensorFlowRuySource_DIR}/ruy/kernel_arm32.cc
- )
- endif(BUILD_ARM32_NEON)
-
- add_library(luci_interpreter_linux_pal_micro STATIC ${PAL_SOURCES})
- set_target_properties(luci_interpreter_linux_pal_micro PROPERTIES POSITION_INDEPENDENT_CODE ON)
- target_include_directories(luci_interpreter_linux_pal_micro SYSTEM PRIVATE
- "${TensorFlowRuySource_DIR}"
- "${TensorFlowGEMMLowpSource_DIR}"
- "${TensorFlowEigenSource_DIR}"
- "${TensorFlowSource_DIR}"
- )
-
- target_link_libraries(${TGT} PRIVATE Threads::Threads luci_interpreter_linux_pal_micro)
-endmacro()
diff --git a/onert-micro/luci-interpreter/pal/mcu/KernelsToBuild.lst b/onert-micro/luci-interpreter/pal/mcu/KernelsToBuild.lst
index 92039735e..42883192e 100644
--- a/onert-micro/luci-interpreter/pal/mcu/KernelsToBuild.lst
+++ b/onert-micro/luci-interpreter/pal/mcu/KernelsToBuild.lst
@@ -1,9 +1,47 @@
+REGISTER_KERNEL(ABS, Abs)
+REGISTER_KERNEL(ADD, Add)
+REGISTER_KERNEL(AVERAGE_POOL_2D, AveragePool2D)
+REGISTER_KERNEL(ARG_MAX, ArgMax)
+REGISTER_KERNEL(ARG_MIN, ArgMin)
+REGISTER_KERNEL(DIV, Div)
+REGISTER_KERNEL(ADD_N, AddN)
REGISTER_KERNEL(FULLY_CONNECTED, FullyConnected)
REGISTER_KERNEL(CONV_2D, Conv2D)
REGISTER_KERNEL(LOGISTIC, Logistic)
+REGISTER_KERNEL(GATHER, Gather)
+REGISTER_KERNEL(EXP, Exp)
+REGISTER_KERNEL(GREATER, Greater)
+REGISTER_KERNEL(GREATER_EQUAL, GreaterEqual)
REGISTER_KERNEL(EXPAND_DIMS, ExpandDims)
+REGISTER_KERNEL(ELU, Elu)
+REGISTER_KERNEL(EQUAL, Equal)
+REGISTER_KERNEL(FILL, Fill)
+REGISTER_KERNEL(PACK, Pack)
+REGISTER_KERNEL(PAD, Pad)
+REGISTER_KERNEL(PADV2, PadV2)
REGISTER_KERNEL(RESHAPE, Reshape)
+REGISTER_KERNEL(RELU, Relu)
+REGISTER_KERNEL(RELU6, Relu6)
+REGISTER_KERNEL(REDUCE_PROD, ReduceCommon)
+REGISTER_KERNEL(LESS, Less)
+REGISTER_KERNEL(LESS_EQUAL, LessEqual)
+REGISTER_KERNEL(LOGICAL_AND, LogicalAnd)
+REGISTER_KERNEL(LOGICAL_OR, LogicalOr)
+REGISTER_KERNEL(LEAKY_RELU, LeakyRelu)
+REGISTER_KERNEL(MUL, Mul)
REGISTER_KERNEL(MAX_POOL_2D, MaxPool2D)
REGISTER_KERNEL(CONCATENATION, Concatenation)
+REGISTER_KERNEL(SHAPE, Shape)
+REGISTER_KERNEL(NOT_EQUAL, NotEqual)
+REGISTER_KERNEL(SLICE, Slice)
+REGISTER_KERNEL(SUB, Sub)
+REGISTER_KERNEL(SPLIT, Split)
+REGISTER_KERNEL(STRIDED_SLICE, StridedSlice)
+REGISTER_KERNEL(SPLIT_V, SplitV)
+REGISTER_KERNEL(TANH, Tanh)
+REGISTER_KERNEL(TRANSPOSE, Transpose)
REGISTER_KERNEL(SOFTMAX, Softmax)
+REGISTER_KERNEL(WHILE, While)
REGISTER_KERNEL(UNIDIRECTIONAL_SEQUENCE_LSTM, UnidirectionalSequenceLSTM)
+REGISTER_KERNEL(RESIZE_BILINEAR, ResizeBilinear)
+REGISTER_KERNEL(NEG, Neg)
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALAdd.h b/onert-micro/luci-interpreter/pal/mcu/PALAdd.h
new file mode 100644
index 000000000..d9d1f7865
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/mcu/PALAdd.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_ADD_H
+#define LUCI_INTERPRETER_PAL_ADD_H
+
+#include "PALAddCommon.h"
+
+namespace luci_interpreter_pal
+{
+template <>
+inline void Add<int8_t>(const ArithmeticParams &, const int, const int8_t *, const int8_t *,
+ int8_t *)
+{
+ assert(false && "Not IMPL yet");
+}
+
+template <>
+inline void Add<int16_t>(const ArithmeticParams &, const int, const int16_t *, const int16_t *,
+ int16_t *)
+{
+ assert(false && "Not IMPL yet");
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_ADD_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALApplyActivationToVector.h b/onert-micro/luci-interpreter/pal/mcu/PALApplyActivationToVector.h
deleted file mode 100644
index 55076c2f1..000000000
--- a/onert-micro/luci-interpreter/pal/mcu/PALApplyActivationToVector.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_APPLY_ACTIVATION_TO_VECTOR_H
-#define LUCI_INTERPRETER_PAL_APPLY_ACTIVATION_TO_VECTOR_H
-
-#include <algorithm>
-#include <cassert>
-#include <cmath>
-#include <cstdlib>
-
-#include "tensorflow/lite/c/builtin_op_data.h"
-
-namespace luci_interpreter_pal
-{
-
-// Dynamic (non-fused) activation functor. perhaps it is worth having
-// template instantiation?
-// TODO(aselle): Make this more efficient by pulling the switch to conv_eval
-// using template inlining.
-class ActivationFunctor
-{
-public:
- explicit ActivationFunctor(TfLiteFusedActivation act) : act_(act) {}
-
- float operator()(float a) const
- {
- switch (act_)
- {
- case kTfLiteActNone:
- return a;
- case kTfLiteActRelu:
- return a < 0.f ? 0.f : a;
- case kTfLiteActRelu6:
- return std::max(0.f, std::min(a, 6.f));
- case kTfLiteActTanh:
- return std::tanh(a);
- case kTfLiteActSigmoid:
- return 1.0f / (1.0f + std::exp(-a));
- default:
- assert(false && "Activation functor is not supported");
- }
- }
-
-private:
- TfLiteFusedActivation act_;
-};
-
-inline void ApplyActivationToVector(const float *vector, int v_size,
- TfLiteFusedActivation activation, float *result)
-{
- auto activation_func = ActivationFunctor(activation);
- for (int v = 0; v < v_size; v++)
- {
- *result++ = (activation_func)(*vector++);
- }
-}
-
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_APPLY_ACTIVATION_TO_VECTOR_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALArgMax.h b/onert-micro/luci-interpreter/pal/mcu/PALArgMax.h
deleted file mode 100644
index 84147b205..000000000
--- a/onert-micro/luci-interpreter/pal/mcu/PALArgMax.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_ARGMAX_H
-#define LUCI_INTERPRETER_PAL_ARGMAX_H
-
-#include <tensorflow/lite/kernels/internal/reference/arg_min_max.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T1, typename T2, typename T3>
-static inline void ArgMinMax(const tflite::RuntimeShape &input1_shape, const T1 *input1_data,
- const T2 *axis, const tflite::RuntimeShape &output_shape,
- T3 *output_data, const std::greater<T1> cmp)
-{
- tflite::reference_ops::ArgMinMax(input1_shape, input1_data, axis, output_shape, output_data, cmp);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_ARGMAX_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALAveragePool2D.h b/onert-micro/luci-interpreter/pal/mcu/PALAveragePool2D.h
new file mode 100644
index 000000000..ef5fe7223
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/mcu/PALAveragePool2D.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2020 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_AVERAGE_POOL_2D_H
+#define LUCI_INTERPRETER_PAL_AVERAGE_POOL_2D_H
+
+#include "PALAveragePool2DCommon.h"
+
+namespace luci_interpreter_pal
+{
+// TODO: add S8 and S16 kernel
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_AVERAGE_POOL_2D_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALAveragePool2d.h b/onert-micro/luci-interpreter/pal/mcu/PALAveragePool2d.h
deleted file mode 100644
index fe93b67f0..000000000
--- a/onert-micro/luci-interpreter/pal/mcu/PALAveragePool2d.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_AVERAGEPOOL2D_H
-#define LUCI_INTERPRETER_PAL_AVERAGEPOOL2D_H
-
-#include <tensorflow/lite/kernels/internal/reference/integer_ops/pooling.h>
-#include <tensorflow/lite/kernels/internal/reference/pooling.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void AveragePool(const tflite::PoolParams &params,
- const tflite::RuntimeShape &input_shape, const T *input_data,
- const tflite::RuntimeShape &output_shape, T *output_data,
- const tflite::RuntimeShape &scratchpad_shape, T *scratchpad_data)
-{
- {
- // MARK: At this moment this operation doesn't support
- assert(false && "AveragePool NYI");
- (void)params;
- (void)input_shape;
- (void)input_data;
- (void)output_shape;
- (void)output_data;
- (void)scratchpad_shape;
- (void)scratchpad_data;
- }
-}
-
-template <>
-inline void AveragePool<int8_t>(const tflite::PoolParams &params,
- const tflite::RuntimeShape &input_shape, const int8_t *input_data,
- const tflite::RuntimeShape &output_shape, int8_t *output_data,
- const tflite::RuntimeShape &scratchpad_shape,
- int8_t *scratchpad_data)
-{
- (void)scratchpad_shape;
- (void)scratchpad_data;
-
- tflite::reference_integer_ops::AveragePool(params, input_shape, input_data, output_shape,
- output_data);
-}
-
-static inline void SetupScratchpadTensor(luci_interpreter::Tensor *scratchpad,
- const luci_interpreter::DataType &input_data_type,
- const tflite::RuntimeShape &input_shape,
- const tflite::RuntimeShape &output_shape)
-
-{
- (void)input_data_type;
- (void)input_shape;
- (void)output_shape;
-
- scratchpad->set_allocatable(false);
-}
-
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_AVERAGEPOOL2D_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALBatchToSpaceND.h b/onert-micro/luci-interpreter/pal/mcu/PALBatchToSpaceND.h
deleted file mode 100644
index 91f92776a..000000000
--- a/onert-micro/luci-interpreter/pal/mcu/PALBatchToSpaceND.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_BATCHTOSPACEND_H
-#define LUCI_INTERPRETER_PAL_BATCHTOSPACEND_H
-
-#include <tensorflow/lite/kernels/internal/reference/batch_to_space_nd.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void
-BatchToSpaceND(const tflite::RuntimeShape &unextended_input1_shape, const T *input1_data,
- const tflite::RuntimeShape &unextended_input2_shape, const int32_t *block_shape_data,
- const tflite::RuntimeShape &unextended_input3_shape, const int32_t *crops_data,
- const tflite::RuntimeShape &unextended_output_shape, T *output_data)
-{
- tflite::reference_ops::BatchToSpaceND(
- unextended_input1_shape, input1_data, unextended_input2_shape, block_shape_data,
- unextended_input3_shape, crops_data, unextended_output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_BATCHTOSPACEND_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALConv2d.h b/onert-micro/luci-interpreter/pal/mcu/PALConv2d.h
index 03f01b535..c979f7610 100644
--- a/onert-micro/luci-interpreter/pal/mcu/PALConv2d.h
+++ b/onert-micro/luci-interpreter/pal/mcu/PALConv2d.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,70 +17,16 @@
#ifndef LUCI_INTERPRETER_PAL_CONV2D_H
#define LUCI_INTERPRETER_PAL_CONV2D_H
-
-#include <tensorflow/lite/kernels/internal/reference/conv.h>
-#include <tensorflow/lite/kernels/internal/reference/integer_ops/conv.h>
+#include "PALConv2DCommon.h"
namespace luci_interpreter_pal
{
-static inline void Conv(const tflite::ConvParams &params, const tflite::RuntimeShape &input_shape,
- const float *input_data, const tflite::RuntimeShape &filter_shape,
- const float *filter_data, const tflite::RuntimeShape &bias_shape,
- const float *bias_data, const tflite::RuntimeShape &output_shape,
- float *output_data, const tflite::RuntimeShape &scratchpad_shape,
- float *scratchpad_data)
-{
- (void)scratchpad_shape;
- (void)scratchpad_data;
- tflite::reference_ops::Conv(params, input_shape, input_data, filter_shape, filter_data,
- bias_shape, bias_data, output_shape, output_data,
- tflite::RuntimeShape(), nullptr);
-}
-
-static inline void Conv(const tflite::ConvParams &params, const tflite::RuntimeShape &input_shape,
- const uint8_t *input_data, const tflite::RuntimeShape &filter_shape,
- const uint8_t *filter_data, const tflite::RuntimeShape &bias_shape,
- const int32_t *bias_data, const tflite::RuntimeShape &output_shape,
- uint8_t *output_data, const tflite::RuntimeShape &scratchpad_shape,
- uint8_t *scratchpad_data)
+static inline void QuantizedConvPerChannel(const ConvParams &, const int32_t *, const int8_t *,
+ const int32_t *, const int8_t *, const int32_t *,
+ const int32_t *, int8_t *)
{
- (void)scratchpad_shape;
- (void)scratchpad_data;
- tflite::reference_ops::Conv(params, input_shape, input_data, filter_shape, filter_data,
- bias_shape, bias_data, output_shape, output_data, scratchpad_shape,
- scratchpad_data, nullptr);
+ assert(false && "Not supported yet");
}
-
-static inline void
-ConvPerChannel(const tflite::ConvParams &params, const int32_t *mult, const int32_t *shifts,
- const tflite::RuntimeShape &input_shape, const int8_t *input_data,
- const tflite::RuntimeShape &filter_shape, const int8_t *filter_data,
- const tflite::RuntimeShape &bias_shape, const int32_t *bias_data,
- const tflite::RuntimeShape &output_shape, int8_t *output_data,
- const tflite::RuntimeShape &scratchpad_shape, int8_t *scratchpad_data)
-{
- (void)scratchpad_shape;
- (void)scratchpad_data;
- tflite::reference_integer_ops::ConvPerChannel(params, mult, shifts, input_shape, input_data,
- filter_shape, filter_data, bias_shape, bias_data,
- output_shape, output_data);
-}
-
-static inline void SetupScratchpadTensor(luci_interpreter::Tensor *scratchpad,
- const luci_interpreter::DataType &input_data_type,
- const tflite::ConvParams &params,
- const tflite::RuntimeShape &input_shape,
- const tflite::RuntimeShape &filter_shape,
- const tflite::RuntimeShape &output_shape)
-{
- (void)input_data_type;
- (void)params;
- (void)input_shape;
- (void)filter_shape;
- (void)output_shape;
- (void)scratchpad;
-}
-
} // namespace luci_interpreter_pal
#endif // LUCI_INTERPRETER_PAL_CONV2D_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALDepthToSpace.h b/onert-micro/luci-interpreter/pal/mcu/PALDepthToSpace.h
deleted file mode 100644
index ce5be4352..000000000
--- a/onert-micro/luci-interpreter/pal/mcu/PALDepthToSpace.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_DEPTHTOSPACE_H
-#define LUCI_INTERPRETER_PAL_DEPTHTOSPACE_H
-
-#include <tensorflow/lite/kernels/internal/reference/depth_to_space.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void DepthToSpace(const tflite::DepthToSpaceParams &op_params,
- const tflite::RuntimeShape &unextended_input_shape,
- const T *input_data,
- const tflite::RuntimeShape &unextended_output_shape, T *output_data)
-{
- tflite::reference_ops::DepthToSpace(op_params, unextended_input_shape, input_data,
- unextended_output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_DEPTHTOSPACE_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALDepthwiseConv2d.h b/onert-micro/luci-interpreter/pal/mcu/PALDepthwiseConv2d.h
deleted file mode 100644
index 1cba99652..000000000
--- a/onert-micro/luci-interpreter/pal/mcu/PALDepthwiseConv2d.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_DEPTHWISECONV2D_H
-#define LUCI_INTERPRETER_PAL_DEPTHWISECONV2D_H
-
-#include <tensorflow/lite/kernels/internal/reference/depthwiseconv_float.h>
-#include <tensorflow/lite/kernels/internal/reference/depthwiseconv_uint8.h>
-#include <tensorflow/lite/kernels/internal/reference/integer_ops/depthwise_conv.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void
-DepthwiseConvPerChannel(const tflite::DepthwiseParams &params, const int32_t *output_multiplier,
- const int32_t *output_shift, const tflite::RuntimeShape &input_shape,
- const T *input_data, const tflite::RuntimeShape &filter_shape,
- const T *filter_data, const tflite::RuntimeShape &bias_shape,
- const int32_t *bias_data, const tflite::RuntimeShape &output_shape,
- T *output_data, const tflite::RuntimeShape &scratchpad_shape,
- T *scratchpad_data)
-{
- {
- // MARK: At this moment this operation is not supported
- assert(false && "DepthwiseConvPerChannel NYI");
- (void)params;
- (void)output_multiplier;
- (void)output_shift;
- (void)input_shape;
- (void)output_data;
- (void)input_data;
- (void)filter_shape;
- (void)filter_data;
- (void)bias_shape;
- (void)bias_data;
- (void)output_shape;
- (void)output_data;
- (void)scratchpad_shape;
- (void)scratchpad_data;
- }
-}
-
-template <>
-inline void DepthwiseConvPerChannel<int8_t>(
- const tflite::DepthwiseParams &params, const int32_t *output_multiplier,
- const int32_t *output_shift, const tflite::RuntimeShape &input_shape, const int8_t *input_data,
- const tflite::RuntimeShape &filter_shape, const int8_t *filter_data,
- const tflite::RuntimeShape &bias_shape, const int32_t *bias_data,
- const tflite::RuntimeShape &output_shape, int8_t *output_data,
- const tflite::RuntimeShape &scratchpad_shape, int8_t *scratchpad_data)
-{
- (void)scratchpad_shape;
- (void)scratchpad_data;
- tflite::reference_integer_ops::DepthwiseConvPerChannel(
- params, output_multiplier, output_shift, input_shape, input_data, filter_shape, filter_data,
- bias_shape, bias_data, output_shape, output_data);
-}
-
-static inline void SetupScratchpadTensor(luci_interpreter::Tensor *scratchpad,
- const tflite::DepthwiseParams &params,
- const luci_interpreter::DataType &input_data_type,
- const tflite::RuntimeShape &input_shape,
- const tflite::RuntimeShape &filter_shape,
- const tflite::RuntimeShape &output_shape)
-
-{
- (void)params;
- (void)input_data_type;
- (void)input_shape;
- (void)filter_shape;
- (void)output_shape;
-
- scratchpad->set_allocatable(false);
-}
-
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_DEPTHWISECONV2D_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALDequantize.h b/onert-micro/luci-interpreter/pal/mcu/PALDequantize.h
deleted file mode 100644
index a11abef4b..000000000
--- a/onert-micro/luci-interpreter/pal/mcu/PALDequantize.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_DEQUANTIZE_H
-#define LUCI_INTERPRETER_PAL_DEQUANTIZE_H
-
-#include "tensorflow/lite/kernels/internal/reference/integer_ops/dequantize.h"
-#include "PALreference_ops.h"
-
-namespace luci_interpreter_pal
-{
-
-template <typename T>
-static inline void Dequantize(tflite::DequantizationParams &params,
- const tflite::RuntimeShape &input_shape, const T *input_data,
- const tflite::RuntimeShape &output_shape, float *output_data)
-{
- tflite::reference_integer_ops::Dequantize<T>(params, input_shape, input_data, output_shape,
- output_data);
-}
-
-static inline void Dequantize(tflite::DequantizationParams &params,
- const tflite::RuntimeShape &input_shape, const uint8_t *input_data,
- const tflite::RuntimeShape &output_shape, float *output_data)
-{
- tflite::reference_ops::Dequantize(params, input_shape, input_data, output_shape, output_data);
-}
-
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_DEQUANTIZE_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALFullyConnected.h b/onert-micro/luci-interpreter/pal/mcu/PALFullyConnected.h
index 25d4dcf43..4a024b137 100644
--- a/onert-micro/luci-interpreter/pal/mcu/PALFullyConnected.h
+++ b/onert-micro/luci-interpreter/pal/mcu/PALFullyConnected.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,48 +15,41 @@
* limitations under the License.
*/
-#ifndef LUCI_INTERPRETER_PAL_FULLYCONNECTED_H
-#define LUCI_INTERPRETER_PAL_FULLYCONNECTED_H
+#ifndef LUCI_INTERPRETER_PAL_FULLY_CONNECTED_H
+#define LUCI_INTERPRETER_PAL_FULLY_CONNECTED_H
-#include <tensorflow/lite/kernels/internal/reference/fully_connected.h>
-#include <tensorflow/lite/kernels/internal/reference/integer_ops/fully_connected.h>
+#include "PALFullyConnectedCommon.h"
namespace luci_interpreter_pal
{
-template <typename T>
-static inline void FullyConnected(const tflite::FullyConnectedParams &params,
- const tflite::RuntimeShape &input_shape, const T *input_data,
- const tflite::RuntimeShape &filter_shape, const T *filter_data,
- const tflite::RuntimeShape &bias_shape, const int32_t *bias_data,
- const tflite::RuntimeShape &output_shape, T *output_data)
+
+template <>
+inline void
+FullyConnected(const luci_interpreter_pal::FullyConnectedParams &params, const int32_t *input_shape,
+ const int8_t *input_data, const int32_t *filter_shape, const int8_t *filter_data,
+ const int32_t *bias_data, const int32_t *output_shape, int8_t *output_data)
{
- {
- // MARK: At this moment this operation is not supported
- assert(false && "FullyConnected NYI");
- (void)params;
- (void)input_shape;
- (void)input_data;
- (void)filter_shape;
- (void)filter_data;
- (void)bias_shape;
- (void)bias_data;
- (void)output_shape;
- (void)output_data;
- }
+ // MARK: At this moment this operation doesn't support
+ assert(false && "FullyConnected INT8 NYI");
+ (void)params;
+ (void)input_shape;
+ (void)input_data;
+ (void)filter_shape;
+ (void)filter_data;
+ (void)bias_data;
+ (void)output_shape;
+ (void)output_data;
}
template <>
-inline void
-FullyConnected<int8_t>(const tflite::FullyConnectedParams &params,
- const tflite::RuntimeShape &input_shape, const int8_t *input_data,
- const tflite::RuntimeShape &filter_shape, const int8_t *filter_data,
- const tflite::RuntimeShape &bias_shape, const int32_t *bias_data,
- const tflite::RuntimeShape &output_shape, int8_t *output_data)
+inline void FullyConnected(const luci_interpreter_pal::FullyConnectedParams &, const int32_t *,
+ const int16_t *, const int32_t *, const int8_t *, const int64_t *,
+ const int32_t *, int16_t *)
{
- tflite::reference_integer_ops::FullyConnected(params, input_shape, input_data, filter_shape,
- filter_data, bias_shape, bias_data, output_shape,
- output_data);
+ // MARK: At this moment this operation doesn't support
+ assert(false && "FullyConnected INT8 NYI");
}
+
} // namespace luci_interpreter_pal
-#endif // LUCI_INTERPRETER_PAL_FULLYCONNECTED_H
+#endif // LUCI_INTERPRETER_PAL_FULLY_CONNECTED_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALL2Normalize.h b/onert-micro/luci-interpreter/pal/mcu/PALL2Normalize.h
deleted file mode 100644
index 16bc4ae8a..000000000
--- a/onert-micro/luci-interpreter/pal/mcu/PALL2Normalize.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_L2NORMALIZE_H
-#define LUCI_INTERPRETER_PAL_L2NORMALIZE_H
-
-#include <tensorflow/lite/kernels/internal/reference/l2normalization.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void L2Normalization(const tflite::L2NormalizationParams &op_params,
- const tflite::RuntimeShape &input_shape, const T *input_data,
- const tflite::RuntimeShape &output_shape, T *output_data)
-{
- tflite::reference_ops::L2Normalization(op_params, input_shape, input_data, output_shape,
- output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_L2NORMALIZE_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALL2Pool2D.h b/onert-micro/luci-interpreter/pal/mcu/PALL2Pool2D.h
index aa3924e4c..38a302fc6 100644
--- a/onert-micro/luci-interpreter/pal/mcu/PALL2Pool2D.h
+++ b/onert-micro/luci-interpreter/pal/mcu/PALL2Pool2D.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALLeakyRelu.h b/onert-micro/luci-interpreter/pal/mcu/PALLeakyRelu.h
deleted file mode 100644
index 97daddc20..000000000
--- a/onert-micro/luci-interpreter/pal/mcu/PALLeakyRelu.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_LEAKYRELU_H
-#define LUCI_INTERPRETER_PAL_LEAKYRELU_H
-
-#include <tensorflow/lite/kernels/internal/reference/leaky_relu.h>
-
-namespace luci_interpreter_pal
-{
-static inline void LeakyRelu(const tflite::LeakyReluParams &params,
- const tflite::RuntimeShape &input_shape, const float *input_data,
- const tflite::RuntimeShape &output_shape, float *output_data)
-{
- tflite::reference_ops::LeakyRelu(params, input_shape, input_data, output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_LEAKYRELU_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALMaxPool2D.h b/onert-micro/luci-interpreter/pal/mcu/PALMaxPool2D.h
new file mode 100644
index 000000000..a0fff0c6d
--- /dev/null
+++ b/onert-micro/luci-interpreter/pal/mcu/PALMaxPool2D.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2020 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_MAX_POOL_2D_H
+#define LUCI_INTERPRETER_PAL_MAX_POOL_2D_H
+
+#include "PALMaxPool2DCommon.h"
+
+namespace luci_interpreter_pal
+{
+// TODO: Add INT8, INT16 kernels
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_MAX_POOL_2D_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALMul.h b/onert-micro/luci-interpreter/pal/mcu/PALMul.h
index e98d8a25f..7b55cd1c8 100644
--- a/onert-micro/luci-interpreter/pal/mcu/PALMul.h
+++ b/onert-micro/luci-interpreter/pal/mcu/PALMul.h
@@ -18,29 +18,25 @@
#ifndef LUCI_INTERPRETER_PAL_MUL_H
#define LUCI_INTERPRETER_PAL_MUL_H
-#include <tensorflow/lite/kernels/internal/reference/mul.h>
+#include "PALMulCommon.h"
namespace luci_interpreter_pal
{
-template <typename T>
-static inline void Mul(tflite::ArithmeticParams &params, const tflite::RuntimeShape &input1_shape,
- const T *input1_data, const tflite::RuntimeShape &input2_shape,
- const T *input2_data, const tflite::RuntimeShape &output_shape,
- T *output_data)
+
+template <>
+inline void Mul<int8_t>(const ArithmeticParams &, const int, const int8_t *, const int8_t *,
+ int8_t *)
{
- tflite::reference_ops::BroadcastMul4DSlow(params, input1_shape, input1_data, input2_shape,
- input2_data, output_shape, output_data);
+ assert(false && "Not IMPL yet");
}
-template <typename T>
-static inline void
-BroadcastMul4DSlow(tflite::ArithmeticParams &params, const tflite::RuntimeShape &input1_shape,
- const T *input1_data, const tflite::RuntimeShape &input2_shape,
- const T *input2_data, const tflite::RuntimeShape &output_shape, T *output_data)
+template <>
+inline void Mul<int16_t>(const ArithmeticParams &, const int, const int16_t *, const int16_t *,
+ int16_t *)
{
- tflite::reference_ops::BroadcastMul4DSlow(params, input1_shape, input1_data, input2_shape,
- input2_data, output_shape, output_data);
+ assert(false && "Not IMPL yet");
}
+
} // namespace luci_interpreter_pal
#endif // LUCI_INTERPRETER_PAL_MUL_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALNeg.h b/onert-micro/luci-interpreter/pal/mcu/PALNeg.h
deleted file mode 100644
index b4e430ef8..000000000
--- a/onert-micro/luci-interpreter/pal/mcu/PALNeg.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_NEG_H
-#define LUCI_INTERPRETER_PAL_NEG_H
-
-#include <tensorflow/lite/kernels/internal/reference/neg.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void Negate(const tflite::RuntimeShape &input_shape, const T *input_data,
- const tflite::RuntimeShape &output_shape, T *output_data)
-{
- tflite::reference_ops::Negate(input_shape, input_data, output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_NEG_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALQuantize.h b/onert-micro/luci-interpreter/pal/mcu/PALQuantize.h
deleted file mode 100644
index 5d9ea5188..000000000
--- a/onert-micro/luci-interpreter/pal/mcu/PALQuantize.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_QUANTIZE_H
-#define LUCI_INTERPRETER_PAL_QUANTIZE_H
-
-#include "PALreference_ops.h"
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void Quantize(tflite::QuantizationParams &params,
- const tflite::RuntimeShape &input_shape, const float *input_data,
- const tflite::RuntimeShape &output_shape, T *output_data)
-{
- tflite::reference_ops::AffineQuantize(params, input_shape, input_data, output_shape, output_data);
-}
-
-template <typename Input, typename Output>
-static inline void Requantize(const Input *input_data, int32_t size,
- int32_t effective_scale_multiplier, int32_t effective_scale_shift,
- int32_t input_zero_point, int32_t output_zero_point,
- Output *output_data)
-{
- tflite::reference_ops::Requantize(input_data, size, effective_scale_multiplier,
- effective_scale_shift, input_zero_point, output_zero_point,
- output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_QUANTIZE_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALResizeBilinear.h b/onert-micro/luci-interpreter/pal/mcu/PALResizeBilinear.h
deleted file mode 100644
index ce9fc802f..000000000
--- a/onert-micro/luci-interpreter/pal/mcu/PALResizeBilinear.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_RESIZEBILINEAR_H
-#define LUCI_INTERPRETER_PAL_RESIZEBILINEAR_H
-
-#include <tensorflow/lite/kernels/internal/reference/resize_bilinear.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void
-ResizeBilinear(const tflite::ResizeBilinearParams &op_params,
- const tflite::RuntimeShape &unextended_input_shape, const T *input_data,
- const tflite::RuntimeShape &output_size_shape, const int32_t *output_size_data,
- const tflite::RuntimeShape &unextended_output_shape, T *output_data)
-{
- tflite::reference_ops::ResizeBilinear(op_params, unextended_input_shape, input_data,
- output_size_shape, output_size_data,
- unextended_output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_RESIZEBILINEAR_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALResizeNearestNeighbor.h b/onert-micro/luci-interpreter/pal/mcu/PALResizeNearestNeighbor.h
deleted file mode 100644
index 10a38c077..000000000
--- a/onert-micro/luci-interpreter/pal/mcu/PALResizeNearestNeighbor.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_RESIZENEARESTNEIGHBOR_H
-#define LUCI_INTERPRETER_PAL_RESIZENEARESTNEIGHBOR_H
-
-#include <tensorflow/lite/kernels/internal/reference/resize_nearest_neighbor.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void
-ResizeNearestNeighbor(const tflite::ResizeNearestNeighborParams &op_params,
- const tflite::RuntimeShape &unextended_input_shape, const T *input_data,
- const tflite::RuntimeShape &output_size_shape,
- const int32_t *output_size_data,
- const tflite::RuntimeShape &unextended_output_shape, T *output_data)
-{
- tflite::reference_ops::ResizeNearestNeighbor(op_params, unextended_input_shape, input_data,
- output_size_shape, output_size_data,
- unextended_output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_RESIZENEARESTNEIGHBOR_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALSVDF.h b/onert-micro/luci-interpreter/pal/mcu/PALSVDF.h
deleted file mode 100644
index d39a2f109..000000000
--- a/onert-micro/luci-interpreter/pal/mcu/PALSVDF.h
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2020 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_SVDF_H
-#define LUCI_INTERPRETER_PAL_SVDF_H
-
-#include <tensorflow/lite/kernels/internal/reference/svdf.h>
-
-namespace luci_interpreter_pal
-{
-static inline void
-IntegerSVDF(const TfLiteSVDFParams &params, const tflite::RuntimeShape &input_shape,
- const int8_t *input_data, const tflite::RuntimeShape &weight_feature_shape,
- const int8_t *weight_feature_data, const tflite::RuntimeShape &weight_time_shape,
- const int16_t *weight_time_data, const tflite::RuntimeShape &bias_shape,
- const int32_t *bias_data, int16_t *activation_state_data,
- const tflite::RuntimeShape &output_shape, int8_t *output_data, int32_t *scratchpad_data,
- int32_t *output_temp_data, int32_t scale_1_a, int scale_1_b, int32_t scale_2_a,
- int scale_2_b, int32_t input_zp, int32_t output_zp)
-{
- const int n_rank = params.rank;
- const int n_batch = input_shape.Dims(0);
- const int n_input = input_shape.Dims(1);
- const int n_filter = weight_feature_shape.Dims(0);
- const int n_unit = n_filter / n_rank;
- const int n_memory = weight_time_shape.Dims(1);
-
- // Left shift the activation_state.
- {
- int16_t *new_state_start = activation_state_data;
- const int16_t *old_state_start = activation_state_data + 1;
- const int16_t *old_state_end = activation_state_data + n_batch * n_filter * n_memory;
- while (old_state_start != old_state_end)
- {
- *new_state_start++ = *old_state_start++;
- }
- }
-
- // Note: no need to clear the latest activation, matmul is not accumulative.
-
- // Feature matmul.
- {
- const int32_t output_max = std::numeric_limits<int16_t>::max();
- const int32_t output_min = std::numeric_limits<int16_t>::min();
- int16_t *result_in_batch = activation_state_data + (n_memory - 1);
- for (int b = 0; b < n_batch; b++)
- {
- const int8_t *matrix_ptr = weight_feature_data;
- for (int r = 0; r < n_filter; r++)
- {
- int32_t dot_prod = 0;
- const int8_t *vector_in_batch = input_data + b * n_input;
- for (int c = 0; c < n_input; c++)
- {
- dot_prod += *matrix_ptr++ * (*vector_in_batch++ - input_zp);
- }
- dot_prod = tflite::MultiplyByQuantizedMultiplier(dot_prod, scale_1_a, scale_1_b);
- dot_prod = std::min(std::max(output_min, dot_prod), output_max);
- // This assumes state is symmetrically quantized. Otherwise last bit of
- // state should be initialized to its zero point and accumulate the
- // dot_prod.
- // Equivalent as the following:
- // result_in_batch = zero point, which happens to be zero.
- // result_in_batch += dot_prod_56.
- *result_in_batch = dot_prod;
- result_in_batch += n_memory;
- }
- }
- }
-
- // Time.
- {
- for (int b = 0; b < n_batch; ++b)
- {
- int32_t *scratch_ptr_batch = scratchpad_data + b * n_filter;
-
- // Perform batched vector dot product:
- const int16_t *vector1_ptr = weight_time_data;
- const int16_t *vector2_ptr = activation_state_data + b * n_memory * n_filter;
-
- for (int i = 0; i < n_filter; i++)
- {
- *scratch_ptr_batch = 0;
- for (int j = 0; j < n_memory; j++)
- {
- *scratch_ptr_batch += *vector1_ptr++ * *vector2_ptr++;
- }
- scratch_ptr_batch++;
- }
- }
- }
-
- // Reduce, add bias, rescale, activation.
- {
- // Add bias.
- if (bias_data)
- {
- // Vector batch assign:
- for (int i = 0; i < n_batch; ++i)
- {
- int32_t *output_ptr = output_temp_data + i * n_unit;
- const int32_t *bias_ptr = bias_data;
- for (int j = 0; j < n_unit; ++j)
- {
- *output_ptr++ = *bias_ptr++;
- }
- }
- }
- else
- {
- int32_t *output_ptr = output_temp_data;
- for (int i = 0; i < n_batch * n_unit; ++i)
- {
- *output_ptr++ = 0;
- }
- }
-
- // Reduce.
- for (int b = 0; b < n_batch; ++b)
- {
- int32_t *output_temp_ptr = output_temp_data + b * n_unit;
- int32_t *scratch_ptr_batch = scratchpad_data + b * n_filter;
-
- // Reduction sum vector
- for (int i = 0; i < n_unit; ++i)
- {
- for (int j = 0; j < n_rank; ++j)
- {
- output_temp_ptr[i] += *scratch_ptr_batch++;
- }
- }
- }
-
- // Rescale.
- const int32_t output_max = std::numeric_limits<int8_t>::max();
- const int32_t output_min = std::numeric_limits<int8_t>::min();
- for (int i = 0; i < n_batch * n_unit; ++i)
- {
- int32_t x1 = output_temp_data[i];
- int32_t x2 = tflite::MultiplyByQuantizedMultiplier(x1, scale_2_a, scale_2_b);
- int32_t x3 = x2 + output_zp;
- int32_t x4 = std::min(std::max(output_min, x3), output_max);
- output_data[i] = static_cast<int8_t>(x4);
- }
- }
-}
-static inline void
-FloatSVDF(const TfLiteSVDFParams &params, const tflite::RuntimeShape &input_shape,
- const float *input_data, const tflite::RuntimeShape &weight_feature_shape,
- const float *weight_feature_data, const tflite::RuntimeShape &weight_time_shape,
- const float *weight_time_data, const tflite::RuntimeShape &bias_shape,
- const float *bias_data, float *scratchpad_data, float *activation_state_data,
- const tflite::RuntimeShape &output_shape, float *output_data)
-{
- const int32_t rank = params.rank;
- const int32_t batch_size = input_shape.Dims(0);
- const int32_t input_size = input_shape.Dims(1);
- const int32_t num_filters = weight_feature_shape.Dims(0);
- const int32_t num_units = num_filters / rank;
- const int32_t memory_size = weight_time_shape.Dims(1);
-
- // Left shift the activation_state.
- {
- float *new_state_start = activation_state_data;
- const float *old_state_start = activation_state_data + 1;
- const float *old_state_end = activation_state_data + batch_size * num_filters * memory_size;
- while (old_state_start != old_state_end)
- {
- *new_state_start++ = *old_state_start++;
- }
- }
-
- // Note: no need to clear the latest activation, matmul is not accumulative.
-
- // Compute conv1d(inputs, weights_feature).
- // The activation_state's rightmost column is used to save current cycle
- // activation. This is achieved by starting at state_ptr[memory_size - 1] and
- // having the stride equal to memory_size.
-
- // Perform batched matrix vector multiply operation:
- {
- const float *matrix = weight_feature_data;
- const float *vector = input_data;
- float *result = &activation_state_data[memory_size - 1];
- float *result_in_batch = result;
- for (int i = 0; i < batch_size; ++i)
- {
- const float *matrix_ptr = matrix;
- for (int j = 0; j < num_filters; ++j)
- {
- float dot_prod = 0.0f;
- const float *vector_in_batch = vector + i * input_size;
- for (int k = 0; k < input_size; ++k)
- {
- dot_prod += *matrix_ptr++ * *vector_in_batch++;
- }
- *result_in_batch = dot_prod;
- result_in_batch += memory_size;
- }
- }
- }
-
- tflite::reference_ops::ApplyTimeWeightsBiasAndActivation(
- batch_size, memory_size, num_filters, num_units, rank, weight_time_data, bias_data,
- params.activation, activation_state_data, scratchpad_data, output_data);
-}
-
-static inline void SetupScratchpadTensor(
- const luci_interpreter::DataType &input_data_type,
- const luci_interpreter::DataType &weight_feature_data_type,
- luci_interpreter::Tensor *scratchpad_1, luci_interpreter::Tensor *scratchpad_2,
- luci_interpreter::Tensor *scratchpad_3, luci_interpreter::Tensor *scratchpad_4,
- luci_interpreter::Tensor *scratchpad_5, luci_interpreter::Tensor *scratchpad_6,
- const luci_interpreter::Shape input_shape, const luci_interpreter::Shape weight_time_shape,
- const int32_t batch_size, const int32_t num_filters, const int32_t num_units)
-{
-
- if (input_data_type == luci_interpreter::DataType::FLOAT32 &&
- (weight_feature_data_type == luci_interpreter::DataType::S8 ||
- weight_feature_data_type == luci_interpreter::DataType::U8))
- {
- (void)input_shape;
- (void)weight_time_shape;
- (void)scratchpad_3;
- (void)scratchpad_4;
- (void)scratchpad_5;
- (void)scratchpad_6;
-
- assert(false && "Hybrid type is not currently supported for mcu platform");
- }
-
- // Resize scratchpad_1 tensor
- scratchpad_1->resize({batch_size, num_filters});
-
- if (input_data_type == luci_interpreter::DataType::S8)
- {
- // Resize scratchpad_2 for full_integer op
- scratchpad_2->resize({batch_size, num_units});
- }
-}
-
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_SVDF_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALSoftmax.h b/onert-micro/luci-interpreter/pal/mcu/PALSoftmax.h
deleted file mode 100644
index cecf38f36..000000000
--- a/onert-micro/luci-interpreter/pal/mcu/PALSoftmax.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_SOFTMAX_H
-#define LUCI_INTERPRETER_PAL_SOFTMAX_H
-
-#include <tensorflow/lite/kernels/internal/reference/softmax.h>
-
-namespace luci_interpreter_pal
-{
-static inline void PopulateSoftmaxLookupTable(tflite::SoftmaxParams *data, float input_scale,
- float beta)
-{
- // Do nothing for mcu
- (void)data;
- (void)input_scale;
- (void)beta;
-}
-
-static inline void InitializeParams(tflite::SoftmaxParams *params, float input_scale, float beta)
-{
- // TODO Impl it
- assert(false && "Softmax NYI");
- (void)params;
- (void)input_scale;
- (void)beta;
-}
-
-template <typename T>
-static inline void Softmax(const tflite::SoftmaxParams &params,
- const tflite::RuntimeShape &input_shape, const T *input_data,
- const tflite::RuntimeShape &output_shape, T *output_data)
-{
- // TODO Impl it
- // MARK: At this moment this operation doesn't support on mcu
- assert(false && "Softmax NYI");
- (void)params;
- (void)input_shape;
- (void)input_data;
- (void)output_shape;
- (void)output_data;
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_SOFTMAX_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALSpaceToBatchND.h b/onert-micro/luci-interpreter/pal/mcu/PALSpaceToBatchND.h
deleted file mode 100644
index b2df23c95..000000000
--- a/onert-micro/luci-interpreter/pal/mcu/PALSpaceToBatchND.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_SPACETOBATCHND_H
-#define LUCI_INTERPRETER_PAL_SPACETOBATCHND_H
-
-#include <tensorflow/lite/kernels/internal/reference/space_to_batch_nd.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void
-SpaceToBatchND(const tflite::SpaceToBatchParams &params,
- const tflite::RuntimeShape &unextended_input1_shape, const T *input1_data,
- const tflite::RuntimeShape &unextended_input2_shape, const int32_t *block_shape_data,
- const tflite::RuntimeShape &unextended_input3_shape, const int32_t *paddings_data,
- const tflite::RuntimeShape &unextended_output_shape, T *output_data)
-{
- tflite::reference_ops::SpaceToBatchND(
- params, unextended_input1_shape, input1_data, unextended_input2_shape, block_shape_data,
- unextended_input3_shape, paddings_data, unextended_output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_SPACETOBATCHND_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALSpaceToDepth.h b/onert-micro/luci-interpreter/pal/mcu/PALSpaceToDepth.h
deleted file mode 100644
index 7866cc2c6..000000000
--- a/onert-micro/luci-interpreter/pal/mcu/PALSpaceToDepth.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_SPACETODEPTH_H
-#define LUCI_INTERPRETER_PAL_SPACETODEPTH_H
-
-#include <tensorflow/lite/kernels/internal/reference/space_to_depth.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void SpaceToDepth(const tflite::SpaceToDepthParams &op_params,
- const tflite::RuntimeShape &unextended_input_shape,
- const T *input_data,
- const tflite::RuntimeShape &unextended_output_shape, T *output_data)
-{
- tflite::reference_ops::SpaceToDepth(op_params, unextended_input_shape, input_data,
- unextended_output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_SPACETODEPTH_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALSub.h b/onert-micro/luci-interpreter/pal/mcu/PALSub.h
deleted file mode 100644
index 2269bc3a6..000000000
--- a/onert-micro/luci-interpreter/pal/mcu/PALSub.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_SUB_H
-#define LUCI_INTERPRETER_PAL_SUB_H
-
-#include <tensorflow/lite/kernels/internal/reference/sub.h>
-
-namespace luci_interpreter_pal
-{
-template <typename T>
-static inline void Sub(const tflite::ArithmeticParams &params,
- const tflite::RuntimeShape &input1_shape, const T *input1_data,
- const tflite::RuntimeShape &input2_shape, const T *input2_data,
- const tflite::RuntimeShape &output_shape, T *output_data)
-{
- tflite::reference_ops::Sub(params, input1_shape, input1_data, input2_shape, input2_data,
- output_shape, output_data);
-}
-} // namespace luci_interpreter_pal
-
-#endif // LUCI_INTERPRETER_PAL_SUB_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALUnidirectionalSequenceLSTM.h b/onert-micro/luci-interpreter/pal/mcu/PALUnidirectionalSequenceLSTM.h
index 287f30314..35592ac66 100644
--- a/onert-micro/luci-interpreter/pal/mcu/PALUnidirectionalSequenceLSTM.h
+++ b/onert-micro/luci-interpreter/pal/mcu/PALUnidirectionalSequenceLSTM.h
@@ -18,614 +18,18 @@
#ifndef LUCI_INTERPRETER_PAL_UNIDIRECTIONAL_SEQUENCE_LSTM_H
#define LUCI_INTERPRETER_PAL_UNIDIRECTIONAL_SEQUENCE_LSTM_H
-#include "kernels/UnidirectionalSequenceLSTM.h"
-#include "tensorflow/lite/kernels/internal/reference/fully_connected.h"
-#include "tensorflow/lite/kernels/internal/reference/integer_ops/logistic.h"
-#include "tensorflow/lite/kernels/internal/reference/logistic.h"
-#include "tensorflow/lite/kernels/internal/reference/integer_ops/tanh.h"
-#include "tensorflow/lite/kernels/internal/reference/tanh.h"
+#include "PALUnidirectionalSequenceLSTMCommon.h"
namespace luci_interpreter_pal
{
-namespace lstm_internal
-{
-namespace
-{
-// Possible fused activation functions.
-typedef enum
-{
- kTfLiteActNone = 0,
- kTfLiteActRelu,
- kTfLiteActReluN1To1, // min(max(-1, x), 1)
- kTfLiteActRelu6, // min(max(0, x), 6)
- kTfLiteActTanh,
- kTfLiteActSignBit,
- kTfLiteActSigmoid,
-} TfLiteFusedActivation;
-
-} // namespace
-
-template <typename T>
-inline T activationFunctionWithMinMax(T x, T output_activation_min, T output_activation_max)
-{
- using std::max;
- using std::min;
- return min(max(x, output_activation_min), output_activation_max);
-}
-
-template <typename T>
-inline void mul(const luci_interpreter::lstm::ArithmeticParams *params,
- const tflite::RuntimeShape &input1_shape, const T *input1_data,
- const tflite::RuntimeShape &input2_shape, const T *input2_data,
- const tflite::RuntimeShape &output_shape, T *output_data)
-{
- T output_activation_min = params->quantized_activation_min;
- T output_activation_max = params->quantized_activation_max;
-
- const int flat_size = input1_shape.FlatSize();
- for (int i = 0; i < flat_size; ++i)
- {
- output_data[i] = activationFunctionWithMinMax(input1_data[i] * input2_data[i],
- output_activation_min, output_activation_max);
- }
-}
-
-#ifndef DIS_QUANT
-inline int32_t multiplyByQuantizedMultiplier(int32_t x, int32_t quantized_multiplier, int shift)
-{
- using gemmlowp::RoundingDivideByPOT;
- using gemmlowp::SaturatingRoundingDoublingHighMul;
- int left_shift = shift > 0 ? shift : 0;
- int right_shift = shift > 0 ? 0 : -shift;
- return RoundingDivideByPOT(
- SaturatingRoundingDoublingHighMul(x * (1 << left_shift), quantized_multiplier), right_shift);
-}
-
-template <typename InputType, typename WeightType, typename OutputType, typename BiasType>
-void fullyConnectedInteger(const tflite::FullyConnectedParams &params,
- const tflite::RuntimeShape &input_shape, const InputType *input_data,
- const tflite::RuntimeShape &filter_shape, const WeightType *filter_data,
- const tflite::RuntimeShape &bias_shape, const BiasType *bias_data,
- const tflite::RuntimeShape &output_shape, OutputType *output_data)
-{
- const int32_t input_offset = params.input_offset;
- const int32_t filter_offset = params.weights_offset;
- const int32_t output_offset = params.output_offset;
- const int32_t output_multiplier = params.output_multiplier;
- const int output_shift = params.output_shift;
- const int32_t output_activation_min = params.quantized_activation_min;
- const int32_t output_activation_max = params.quantized_activation_max;
- TFLITE_DCHECK_GE(filter_shape.DimensionsCount(), 2);
- TFLITE_DCHECK_GE(output_shape.DimensionsCount(), 1);
-
- TFLITE_DCHECK_LE(output_activation_min, output_activation_max);
- const int filter_dim_count = filter_shape.DimensionsCount();
- const int output_dim_count = output_shape.DimensionsCount();
- const int batches = FlatSizeSkipDim(output_shape, output_dim_count - 1);
- const int output_depth = output_shape.Dims(output_dim_count - 1);
- TFLITE_DCHECK_LE(output_depth, filter_shape.Dims(filter_dim_count - 2));
- const int accum_depth = filter_shape.Dims(filter_dim_count - 1);
- for (int b = 0; b < batches; ++b)
- {
- for (int out_c = 0; out_c < output_depth; ++out_c)
- {
- BiasType acc = 0;
- for (int d = 0; d < accum_depth; ++d)
- {
- int32_t input_val = input_data[b * accum_depth + d];
- int32_t filter_val = filter_data[out_c * accum_depth + d];
- acc += (filter_val + filter_offset) * (input_val + input_offset);
- }
- if (bias_data)
- {
- acc += bias_data[out_c];
- }
- int32_t acc_scaled = multiplyByQuantizedMultiplier(acc, output_multiplier, output_shift);
- acc_scaled += output_offset;
- acc_scaled = std::max(acc_scaled, output_activation_min);
- acc_scaled = std::min(acc_scaled, output_activation_max);
- output_data[out_c + output_depth * b] = static_cast<OutputType>(acc_scaled);
- }
- }
-}
-
-void fullyConnected(const tflite::FullyConnectedParams &params,
- const tflite::RuntimeShape &input_shape, const int8_t *input_data,
- const tflite::RuntimeShape &filter_shape, const int8_t *filter_data,
- const tflite::RuntimeShape &bias_shape, const int32_t *bias_data,
- const tflite::RuntimeShape &output_shape, int16_t *output_data)
-{
- return fullyConnectedInteger(params, input_shape, input_data, filter_shape, filter_data,
- bias_shape, bias_data, output_shape, output_data);
-}
-
-void fullyConnected(const tflite::FullyConnectedParams &params,
- const tflite::RuntimeShape &input_shape, const int16_t *input_data,
- const tflite::RuntimeShape &filter_shape, const int8_t *filter_data,
- const tflite::RuntimeShape &bias_shape, const int64_t *bias_data,
- const tflite::RuntimeShape &output_shape, int16_t *output_data)
-{
- return fullyConnectedInteger(params, input_shape, input_data, filter_shape, filter_data,
- bias_shape, bias_data, output_shape, output_data);
-}
-
-template <typename InputType, typename OutputType>
-void mulElementwise(int size, const luci_interpreter::lstm::ArithmeticParams *params,
- const InputType *input1_data, const InputType *input2_data,
- OutputType *output_data)
-{
- for (int i = 0; i < size; ++i)
- {
- const int32_t input1_val = params->input1_offset + input1_data[i];
- const int32_t input2_val = params->input2_offset + input2_data[i];
- const int32_t unclamped_result =
- params->output_offset + multiplyByQuantizedMultiplier(input1_val * input2_val,
- params->output_multiplier,
- params->output_shift);
- const int32_t clamped_output =
- std::min(params->quantized_activation_max,
- std::max(params->quantized_activation_min, unclamped_result));
- output_data[i] = static_cast<OutputType>(clamped_output);
- }
-}
-
-// Input and output have the same shape in LSTM
-void mul(const tflite::RuntimeShape &shape, const luci_interpreter::lstm::ArithmeticParams *params,
- const int16_t *input1_data, const int16_t *input2_data, int8_t *output_data)
-{
- return mulElementwise<int16_t, int8_t>(shape.FlatSize(), params, input1_data, input2_data,
- output_data);
-}
-
-// Input and output have the same shape in LSTM
-void mul(const tflite::RuntimeShape &shape, const luci_interpreter::lstm::ArithmeticParams *params,
- const int16_t *input1_data, const int16_t *input2_data, int16_t *output_data)
-{
- return mulElementwise(shape.FlatSize(), params, input1_data, input2_data, output_data);
-}
-
-void addElementWise(const int16_t *input_1, const int16_t *input_2, int n_batch, int n_input,
- int16_t *output)
-{
- for (int batch = 0; batch < n_batch; ++batch)
- {
- for (int i = 0; i < n_input; ++i)
- {
- const int index = batch * n_input + i;
- int32_t sum = input_1[index] + input_2[index];
- const int32_t sum_clamped =
- std::min(static_cast<int32_t>(std::numeric_limits<int16_t>::max()),
- std::max(static_cast<int32_t>(std::numeric_limits<int16_t>::min()), sum));
- output[index] = static_cast<int16_t>(sum_clamped);
- }
- }
-}
-
-void tanh(int32_t cell_state_scale_power, const tflite::RuntimeShape &input_data_shape,
- int16_t *input_data, const tflite::RuntimeShape &output_data_shape, int16_t *output_data)
-{
- int32_t tanh_input_left_shift = (15 + cell_state_scale_power) - 3;
- int32_t input_multiplier = 0;
- if (tanh_input_left_shift < 0) /* handling negative shift value */
- {
- tanh_input_left_shift = -tanh_input_left_shift;
- input_multiplier = 3;
- }
- tflite::reference_integer_ops::Tanh(input_multiplier, tanh_input_left_shift, input_data_shape,
- input_data, output_data_shape, output_data);
-}
-
-void sigmoid(const tflite::RuntimeShape &data_shape, int16_t *data)
-{
- tflite::reference_integer_ops::Logistic(0 /*data->input_multiplier*/,
- 0 /*data->input_left_shift */,
- data_shape.FlatSize() /*NumElements(input->dims)*/,
- data /* tflite::micro::GetTensorData<int16_t>(input) */,
- data /*tflite::micro::GetTensorData<int16_t>(output) */);
-}
-
-void clipping(const int v_size, const luci_interpreter::lstm::CellStateInfo *cell_state_info,
- int16_t *vector)
-{
- for (int i = 0; i < v_size; i++)
- {
- vector[i] = std::max(std::min(cell_state_info->quantized_cell_clip, vector[i]),
- static_cast<int16_t>(-cell_state_info->quantized_cell_clip));
- }
-}
-#endif // DIS_QUANT
-
-#ifndef DIS_FLOAT
-void fullyConnected(const tflite::FullyConnectedParams &params,
- const tflite::RuntimeShape &input_shape, const float *input_data,
- const tflite::RuntimeShape &filter_shape, const float *filter_data,
- const tflite::RuntimeShape &bias_shape, const float *bias_data,
- const tflite::RuntimeShape &output_shape, float *output_data)
-{
- return tflite::reference_ops::FullyConnected(params, input_shape, input_data, filter_shape,
- filter_data, bias_shape, bias_data, output_shape,
- output_data);
-}
-
-// Input and output have the same shape in LSTM
-void mul(const tflite::RuntimeShape &shape, const luci_interpreter::lstm::ArithmeticParams *params,
- const float *input1_data, const float *input2_data, float *output_data)
-{
- return mul(params, shape, input1_data, shape, input2_data, shape, output_data);
-}
-
-void addElementWise(const float *input_1, const float *input_2, int n_batch, int n_input,
- float *output)
-{
- for (int batch = 0; batch < n_batch; ++batch)
- {
- for (int i = 0; i < n_input; ++i)
- {
- const int index = batch * n_input + i;
- output[index] = input_1[index] + input_2[index];
- }
- }
-}
-
-void tanh(int32_t cell_state_scale_power, const tflite::RuntimeShape &input_data_shape,
- float *input_data, const tflite::RuntimeShape &output_data_shape, float *output_data)
-{
- tflite::reference_ops::Tanh(input_data_shape, input_data, output_data_shape, output_data);
-}
-
-void sigmoid(const tflite::RuntimeShape &data_shape, float *data)
-{
- tflite::reference_ops::Logistic(data_shape, data, data_shape, data);
-}
-
-void clipping(const int v_size, const luci_interpreter::lstm::CellStateInfo *cell_state_info,
- float *vector)
-{
- for (int i = 0; i < v_size; i++)
- {
- vector[i] =
- std::max(std::min(cell_state_info->cell_clip, vector[i]), -cell_state_info->cell_clip);
- }
-}
-#endif // DIS_FLOAT
-
-// Size information about the LSTM kernel, which is deduced from tensors stored
-// in the flat buffer file.
-struct LstmSizeInfo
-{
- bool time_major;
- int32_t batch_size;
- int32_t time_steps;
- int32_t input_dimension;
- int32_t state_dimension;
-};
-
-class LstmStepManager
-{
-public:
- LstmStepManager() = delete;
- // Does not take any ownership, and all pointers must refer to valid objects
- // that outlive the one constructed.
- explicit LstmStepManager(const LstmSizeInfo &size_info) : size_info_(size_info) {}
-
- void updateTime()
- {
- current_time_ += 1;
- // default as one batch per inference
- int input_step = size_info_.input_dimension;
- int output_step = size_info_.state_dimension;
- // time major: batch inference
- if (size_info_.time_major)
- {
- input_step = input_step * size_info_.batch_size;
- output_step = output_step * size_info_.batch_size;
- }
-
- input_offset_ += input_step;
- output_offset_ += output_step;
- }
-
- void updateBatch()
- {
- current_batch_ += 1;
- TFLITE_DCHECK_LE(current_batch_, size_info_.batch_size);
- // batch inference for time major: no action needed
- if (size_info_.time_major)
- {
- return;
- }
- // otherwise: singe batch inference, go to the next batch
- hidden_state_offset_ += size_info_.state_dimension;
- cell_state_offset_ += size_info_.state_dimension;
- }
-
- void resetTime() { current_time_ = 0; }
-
- tflite::RuntimeShape inputShape() const
- {
- int batch_size = 1;
- if (size_info_.time_major)
- {
- batch_size = size_info_.batch_size;
- }
- const int dims[2] = {batch_size, size_info_.input_dimension};
- const int32_t *dims_data = reinterpret_cast<const int32_t *>(dims);
- return tflite::RuntimeShape(2, dims_data);
- }
-
- tflite::RuntimeShape stateShape() const
- {
- int batch_size = 1;
- if (size_info_.time_major)
- {
- batch_size = size_info_.batch_size;
- }
- const int dims[2] = {batch_size, size_info_.state_dimension};
- const int32_t *dims_data = reinterpret_cast<const int32_t *>(dims);
- return tflite::RuntimeShape(2, dims_data);
- }
-
- int inputOffset() const { return input_offset_; }
-
- int outputOffset() const { return output_offset_; }
-
- int hiddenStateOffset() const { return hidden_state_offset_; }
-
- int cellStateOffset() const { return cell_state_offset_; }
-
-private:
- int32_t current_time_ = 0;
- int32_t current_batch_ = 0;
- int32_t input_offset_ = 0;
- int32_t output_offset_ = 0;
- int32_t hidden_state_offset_ = 0;
- int32_t cell_state_offset_ = 0;
-
- const LstmSizeInfo &size_info_;
-};
-
-// Calculates a single LSTM gate.
-// Implements the following formula:
-// gate = activate(FC(input) + FC(recurrent))
-// Activation is sigmoid except for the "cell" gate (configurable, usually tanh)
-template <typename ActivationType, typename WeightType, typename CellType, typename BiasType>
-void calculateLstmGate(const LstmStepManager *step_info,
- const luci_interpreter::lstm::GateParameters *gate_params,
- // Input FC
- ActivationType *input_data, const circle::Tensor *input_weight,
- const circle::Tensor *input_bias,
- // Recurrent FC
- ActivationType *recurrent_data, const circle::Tensor *recurrent_weight,
- const circle::Tensor *recurrent_bias,
- // Output
- CellType *gate_output,
- // Scratch arrays
- CellType *fc_output_buffer, const TfLiteFusedActivation activation,
- luci_interpreter::BaseRuntimeGraph *runtime_graph)
-{
- // Input FC
- const auto gate_output_shape = step_info->stateShape();
- {
- tflite::FullyConnectedParams op_params{};
- op_params.input_offset = gate_params->input_fc_params.input_offset;
- op_params.weights_offset = gate_params->input_fc_params.weights_offset;
- op_params.output_offset = gate_params->input_fc_params.output_offset;
- op_params.output_multiplier = gate_params->input_fc_params.output_multiplier;
- op_params.output_shift = gate_params->input_fc_params.output_shift;
- op_params.quantized_activation_min = gate_params->input_fc_params.quantized_activation_min;
- op_params.quantized_activation_max = gate_params->input_fc_params.quantized_activation_max;
- op_params.float_activation_max = gate_params->input_fc_params.float_activation_max;
- op_params.float_activation_min = gate_params->input_fc_params.float_activation_min;
-
- fullyConnected(op_params, step_info->inputShape(), input_data + step_info->inputOffset(),
- luci_interpreter::kernels::getTensorShape(input_weight),
- luci_interpreter::kernels::getTensorData<WeightType>(
- runtime_graph->getConstDataByTensor(input_weight)),
- luci_interpreter::kernels::getTensorShape(input_bias),
- luci_interpreter::kernels::getTensorData<BiasType>(
- runtime_graph->getConstDataByTensor(input_bias)),
- gate_output_shape, gate_output);
- }
-
- // Recurrent FC
- {
- tflite::FullyConnectedParams op_params{};
- op_params.input_offset = gate_params->recurrent_fc_params.input_offset;
- op_params.weights_offset = gate_params->recurrent_fc_params.weights_offset;
- op_params.output_offset = gate_params->recurrent_fc_params.output_offset;
- op_params.output_multiplier = gate_params->recurrent_fc_params.output_multiplier;
- op_params.output_shift = gate_params->recurrent_fc_params.output_shift;
- op_params.quantized_activation_min = gate_params->recurrent_fc_params.quantized_activation_min;
- op_params.quantized_activation_max = gate_params->recurrent_fc_params.quantized_activation_max;
- op_params.float_activation_max = gate_params->recurrent_fc_params.float_activation_max;
- op_params.float_activation_min = gate_params->recurrent_fc_params.float_activation_min;
-
- fullyConnected(op_params, step_info->stateShape(),
- recurrent_data + step_info->hiddenStateOffset(),
- luci_interpreter::kernels::getTensorShape(recurrent_weight),
- luci_interpreter::kernels::getTensorData<WeightType>(
- runtime_graph->getConstDataByTensor(recurrent_weight)),
- luci_interpreter::kernels::getTensorShape(recurrent_bias),
- luci_interpreter::kernels::getTensorData<BiasType>(
- runtime_graph->getConstDataByTensor(recurrent_bias)),
- gate_output_shape, fc_output_buffer);
-
- addElementWise(gate_output, fc_output_buffer, /*n_batch=*/gate_output_shape.DimsData()[0],
- /*n_state=*/gate_output_shape.DimsData()[1], gate_output);
-
- switch (activation)
- {
- case TfLiteFusedActivation::kTfLiteActSigmoid:
- sigmoid(gate_output_shape, gate_output);
- break;
- case TfLiteFusedActivation::kTfLiteActTanh:
- {
- // Set the scale power to -12 to avoid shift
- tanh(/*cell_state_scale_power=*/-12, gate_output_shape, gate_output, gate_output_shape,
- gate_output);
- }
- break;
- default:
- // Only Sigmoid or Tanh is used.
- assert(false && "Only Sigmoid or Tanh is used");
- }
- }
-}
-
-// Update the hidden state of the LSTM kernel using the following formula:
-// updated_hidden_state = Tanh(updated_cell_state) * output_gate_output, * means
-// element wise multiplication
-template <typename CellType, typename ActivationType>
-void updateLstmHidden(const LstmStepManager *step_info, CellType *cell_state_data_base,
- ActivationType *hidden_state_data, const CellType *output_gate_output,
- const luci_interpreter::lstm::ArithmeticParams *mul_params,
- int32_t cell_state_scale_power, CellType *buffer)
-{
- auto cell_state_shape = step_info->stateShape();
- CellType *cell_state_data = cell_state_data_base + step_info->cellStateOffset();
- // Tanh(cell_state)
- tanh(cell_state_scale_power, cell_state_shape, cell_state_data, cell_state_shape, buffer);
- // Update the hidden state
- mul(cell_state_shape, mul_params, buffer, output_gate_output,
- hidden_state_data + step_info->hiddenStateOffset());
-}
-
-// Update the cell state using the output from the forget gate, input gate, and
-// cell gate Formula: updated_cell_state = forget_gate_output*cell_state +
-// input_gate_output * cell_gate_output, where * denotes element wise
-// multiplication
-template <typename CellType>
-void updateLstmCell(const LstmStepManager *step_info, CellType *cell_state_data,
- // Gate outputs
- CellType *forget_gate_output, const CellType *input_gate_output,
- const CellType *cell_gate_output,
- // Mul parameters
- const luci_interpreter::lstm::ArithmeticParams &forget_cell_mul_params,
- const luci_interpreter::lstm::ArithmeticParams &input_mul_params,
- const luci_interpreter::lstm::CellStateInfo *cell_state_info, CellType *buffer)
-{
- auto cell_state_shape = step_info->stateShape();
- // Forget Gate x Cell State
- mul(cell_state_shape, &forget_cell_mul_params, forget_gate_output,
- cell_state_data + step_info->cellStateOffset(),
- cell_state_data + step_info->cellStateOffset());
- // Input Gate x Cell Gate
- mul(cell_state_shape, &input_mul_params, input_gate_output, cell_gate_output, buffer);
-
- // Update the cell state
- addElementWise(cell_state_data + step_info->cellStateOffset(), buffer,
- /*n_batch=*/cell_state_shape.DimsData()[0],
- /*n_state=*/cell_state_shape.DimsData()[1],
- cell_state_data + step_info->cellStateOffset());
-
- if (cell_state_info->cell_clip > 0)
- {
- clipping(cell_state_shape.FlatSize(), cell_state_info,
- cell_state_data + step_info->cellStateOffset());
- }
-}
-
-template <typename ActivationType, typename WeightType, typename CellType, typename BiasType>
-void lstmStep(luci_interpreter::lstm::LSTMStruct *lstm_struct,
- luci_interpreter::lstm::LSTMParameters *lstm_params, LstmStepManager *step_info,
- luci_interpreter::lstm::CellStateInfo *cell_state_info,
- ActivationType *output_state_data, CellType *cell_state_data, CellType *scratch0,
- CellType *scratch1, CellType *scratch2, CellType *scratch3,
- luci_interpreter::BaseRuntimeGraph *runtime_graph)
-{
- /*Step1: Calculate gate outputs to prepare cell state update*/
- CellType *gate_internal_buffer = scratch3;
- CellType *forget_gate_output = scratch0;
-
- auto input_data = luci_interpreter::kernels::getTensorData<ActivationType>(
- runtime_graph->getDataByTensor(lstm_struct->input()));
-
- calculateLstmGate<ActivationType, WeightType, CellType, BiasType>(
- step_info, &lstm_params->forget_gate_parameters,
- // Input FC
- input_data, lstm_struct->input_to_forget_weights(), lstm_struct->forget_gate_bias(),
- // Recurrent FC
- output_state_data, lstm_struct->recurrent_to_forget_weights(), nullptr,
- // Output
- forget_gate_output, gate_internal_buffer, TfLiteFusedActivation::kTfLiteActSigmoid,
- runtime_graph);
-
- // Input Gate calculation;
- CellType *input_gate_output = scratch1;
- calculateLstmGate<ActivationType, WeightType, CellType, BiasType>(
- step_info, &lstm_params->input_gate_parameters,
- // Input FC
- input_data, lstm_struct->input_to_input_weights(), lstm_struct->input_gate_bias(),
- // Recurrent FC
- output_state_data, lstm_struct->recurrent_to_input_weights(),
- /*recurrent_bias*/ nullptr,
- // Output
- input_gate_output,
- // Scratch arrays
- gate_internal_buffer, TfLiteFusedActivation::kTfLiteActSigmoid, runtime_graph);
-
- // Cell Gate calculation
- CellType *cell_gate_output = scratch2;
- calculateLstmGate<ActivationType, WeightType, CellType, BiasType>(
- step_info, &lstm_params->cell_gate_parameters,
- // Input FC
- input_data, lstm_struct->input_to_cell_weights(), lstm_struct->cell_gate_bias(),
- // Recurrent FC
- output_state_data, lstm_struct->recurrent_to_cell_weights(),
- /*recurrent_bias*/ nullptr,
- // Output
- cell_gate_output,
- // Scratch arrays
- gate_internal_buffer, TfLiteFusedActivation::kTfLiteActTanh, runtime_graph);
-
- /*Step2: update the cell state */
- {
- // const InterGateParameters& inter_gate_params = op_data.inter_gate_parameters;
- CellType *updated_input_buffer = scratch1; // reuse buffer
-
- updateLstmCell<CellType>(
- step_info, cell_state_data, forget_gate_output, input_gate_output, cell_gate_output,
- lstm_params->inter_gate_parameters.forget_cell_mul_params,
- lstm_params->inter_gate_parameters.input_mul_params, cell_state_info, updated_input_buffer);
- }
-
- {
- /*Step3: update the hidden state */
- CellType *output_gate_output = scratch1; // reuse buffer
- calculateLstmGate<ActivationType, WeightType, CellType, BiasType>(
- step_info, &lstm_params->output_gate_parameters,
- // Input FC
- input_data, lstm_struct->input_to_output_weights(), lstm_struct->output_gate_bias(),
- // Recurrent FC
- output_state_data, lstm_struct->recurrent_to_output_weights(), nullptr,
- // Output
- output_gate_output,
- // Scratch arrays
- gate_internal_buffer, TfLiteFusedActivation::kTfLiteActSigmoid, runtime_graph);
- CellType *tanh_activated_cell_buffer = scratch0; // reuse buffer
- updateLstmHidden<CellType, ActivationType>(
- step_info, cell_state_data, output_state_data, output_gate_output,
- &lstm_params->inter_gate_parameters.output_mul_params,
- cell_state_info->cell_state_scale_power, tanh_activated_cell_buffer);
-
- ActivationType *output_ptr = luci_interpreter::kernels::getTensorData<ActivationType>(
- runtime_graph->getDataByTensor(lstm_struct->output()));
- std::memcpy(output_ptr + step_info->outputOffset(),
- output_state_data + step_info->hiddenStateOffset(),
- step_info->stateShape().FlatSize() * sizeof(ActivationType));
- }
-}
-
-} // namespace lstm_internal
-
// Evaluate the LSTM kernel with (potential) multi-steps and multi-batch input
-template <typename ActivationType, typename WeightType, typename CellType, typename BiasType>
-void evalLSTM(luci_interpreter::lstm::LSTMStruct *lstm_struct,
- luci_interpreter::lstm::LSTMParameters *lstm_params,
- luci_interpreter::lstm::CellStateInfo *cell_state_info,
- ActivationType *output_state_data, CellType *cell_state_data, CellType *scratch0,
- CellType *scratch1, CellType *scratch2, CellType *scratch3,
- luci_interpreter::BaseRuntimeGraph *runtime_graph)
+template <>
+void evalLSTM<int8_t, int8_t, int16_t, int32_t>(
+ luci_interpreter::lstm::LSTMStruct *lstm_struct,
+ luci_interpreter::lstm::LSTMParameters *lstm_params,
+ luci_interpreter::lstm::CellStateInfo *cell_state_info, int8_t *output_state_data,
+ int16_t *cell_state_data, int16_t *scratch0, int16_t *scratch1, int16_t *scratch2,
+ int16_t *scratch3, luci_interpreter::BaseRuntimeGraph *runtime_graph)
{
lstm_internal::LstmSizeInfo size_info;
@@ -646,7 +50,7 @@ void evalLSTM(luci_interpreter::lstm::LSTMStruct *lstm_struct,
{
for (int t = 0; t < size_info.time_steps; t++)
{
- lstm_internal::lstmStep<ActivationType, WeightType, CellType, BiasType>(
+ lstm_internal::lstmStep<int8_t, int8_t, int16_t, int32_t>(
lstm_struct, lstm_params, &step_info, cell_state_info, output_state_data, cell_state_data,
scratch0, scratch1, scratch2, scratch3, runtime_graph);
// prepare for the next time step
@@ -660,7 +64,7 @@ void evalLSTM(luci_interpreter::lstm::LSTMStruct *lstm_struct,
{
for (int t = 0; t < size_info.time_steps; t++)
{
- lstm_internal::lstmStep<ActivationType, WeightType, CellType, BiasType>(
+ lstm_internal::lstmStep<int8_t, int8_t, int16_t, int32_t>(
lstm_struct, lstm_params, &step_info, cell_state_info, output_state_data, cell_state_data,
scratch0, scratch1, scratch2, scratch3, runtime_graph);
// prepare for the next time step
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALreference_ops.h b/onert-micro/luci-interpreter/pal/mcu/PALreference_ops.h
deleted file mode 100644
index 62c720937..000000000
--- a/onert-micro/luci-interpreter/pal/mcu/PALreference_ops.h
+++ /dev/null
@@ -1,1556 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_REFERENCE_OPS_H
-#define LUCI_INTERPRETER_PAL_REFERENCE_OPS_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <algorithm>
-#include <cmath>
-#include <cstring>
-#include <functional>
-#include <limits>
-#include <memory>
-#include <type_traits>
-
-#include "third_party/eigen3/Eigen/Core"
-#include "fixedpoint/fixedpoint.h"
-#include "ruy/profiler/instrumentation.h" // from @ruy
-#include "tensorflow/lite/c/common.h"
-#include "tensorflow/lite/kernels/internal/common.h"
-#include "tensorflow/lite/kernels/internal/quantization_util.h"
-#include "tensorflow/lite/kernels/internal/reference/add.h"
-#include "tensorflow/lite/kernels/internal/reference/add_n.h"
-#include "tensorflow/lite/kernels/internal/reference/arg_min_max.h"
-#include "tensorflow/lite/kernels/internal/reference/batch_matmul.h"
-#include "tensorflow/lite/kernels/internal/reference/batch_to_space_nd.h"
-#include "tensorflow/lite/kernels/internal/reference/binary_function.h"
-#include "tensorflow/lite/kernels/internal/reference/cast.h"
-#include "tensorflow/lite/kernels/internal/reference/ceil.h"
-#include "tensorflow/lite/kernels/internal/reference/comparisons.h"
-#include "tensorflow/lite/kernels/internal/reference/concatenation.h"
-#include "tensorflow/lite/kernels/internal/reference/conv.h"
-#include "tensorflow/lite/kernels/internal/reference/depth_to_space.h"
-#include "tensorflow/lite/kernels/internal/reference/dequantize.h"
-#include "tensorflow/lite/kernels/internal/reference/div.h"
-#include "tensorflow/lite/kernels/internal/reference/elu.h"
-#include "tensorflow/lite/kernels/internal/reference/exp.h"
-#include "tensorflow/lite/kernels/internal/reference/fill.h"
-#include "tensorflow/lite/kernels/internal/reference/floor.h"
-#include "tensorflow/lite/kernels/internal/reference/floor_div.h"
-#include "tensorflow/lite/kernels/internal/reference/floor_mod.h"
-#include "tensorflow/lite/kernels/internal/reference/fully_connected.h"
-#include "tensorflow/lite/kernels/internal/reference/gather.h"
-#include "tensorflow/lite/kernels/internal/reference/hard_swish.h"
-#include "tensorflow/lite/kernels/internal/reference/l2normalization.h"
-#include "tensorflow/lite/kernels/internal/reference/leaky_relu.h"
-#include "tensorflow/lite/kernels/internal/reference/log_softmax.h"
-#include "tensorflow/lite/kernels/internal/reference/logistic.h"
-#include "tensorflow/lite/kernels/internal/reference/maximum_minimum.h"
-#include "tensorflow/lite/kernels/internal/reference/mul.h"
-#include "tensorflow/lite/kernels/internal/reference/neg.h"
-#include "tensorflow/lite/kernels/internal/reference/pad.h"
-#include "tensorflow/lite/kernels/internal/reference/pooling.h"
-#include "tensorflow/lite/kernels/internal/reference/prelu.h"
-#include "tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h"
-#include "tensorflow/lite/kernels/internal/reference/quantize.h"
-#include "tensorflow/lite/kernels/internal/reference/reduce.h"
-#include "tensorflow/lite/kernels/internal/reference/requantize.h"
-#include "tensorflow/lite/kernels/internal/reference/resize_bilinear.h"
-#include "tensorflow/lite/kernels/internal/reference/resize_nearest_neighbor.h"
-#include "tensorflow/lite/kernels/internal/reference/round.h"
-#include "tensorflow/lite/kernels/internal/reference/softmax.h"
-#include "tensorflow/lite/kernels/internal/reference/space_to_batch_nd.h"
-#include "tensorflow/lite/kernels/internal/reference/space_to_depth.h"
-#include "tensorflow/lite/kernels/internal/reference/strided_slice.h"
-#include "tensorflow/lite/kernels/internal/reference/string_comparisons.h"
-#include "tensorflow/lite/kernels/internal/reference/sub.h"
-#include "tensorflow/lite/kernels/internal/reference/tanh.h"
-#include "tensorflow/lite/kernels/internal/reference/transpose.h"
-#include "tensorflow/lite/kernels/internal/reference/transpose_conv.h"
-#include "tensorflow/lite/kernels/internal/strided_slice_logic.h"
-#include "tensorflow/lite/kernels/internal/tensor.h"
-#include "tensorflow/lite/kernels/internal/types.h"
-namespace tflite
-{
-
-namespace reference_ops
-{
-
-template <typename T>
-inline void Relu(const RuntimeShape &input_shape, const T *input_data,
- const RuntimeShape &output_shape, T *output_data)
-{
- const int flat_size = MatchingFlatSize(input_shape, output_shape);
- for (int i = 0; i < flat_size; ++i)
- {
- const T val = input_data[i];
- const T lower = 0;
- const T clamped = val < lower ? lower : val;
- output_data[i] = clamped;
- }
-}
-
-template <typename T>
-inline void Relu1(const RuntimeShape &input_shape, const T *input_data,
- const RuntimeShape &output_shape, T *output_data)
-{
- ruy::profiler::ScopeLabel label("Relu1 (not fused)");
- const int flat_size = MatchingFlatSize(input_shape, output_shape);
- for (int i = 0; i < flat_size; ++i)
- {
- const T val = input_data[i];
- const T upper = 1;
- const T lower = -1;
- const T clamped = val > upper ? upper : val < lower ? lower : val;
- output_data[i] = clamped;
- }
-}
-
-inline void Relu6(const RuntimeShape &input_shape, const float *input_data,
- const RuntimeShape &output_shape, float *output_data)
-{
- ruy::profiler::ScopeLabel label("Relu6 (not fused)");
- const int flat_size = MatchingFlatSize(input_shape, output_shape);
- for (int i = 0; i < flat_size; ++i)
- {
- const float val = input_data[i];
- const float upper = 6;
- const float lower = 0;
- const float clamped = val > upper ? upper : val < lower ? lower : val;
- output_data[i] = clamped;
- }
-}
-
-template <typename T>
-inline void ReluX(const tflite::ReluParams &params, const RuntimeShape &input_shape,
- const T *input_data, const RuntimeShape &output_shape, T *output_data)
-{
- ruy::profiler::ScopeLabel label("Quantized ReluX (not fused)");
- const int flat_size = MatchingFlatSize(input_shape, output_shape);
- for (int i = 0; i < flat_size; ++i)
- {
- const int32 val = static_cast<int32_t>(input_data[i]);
- int32 clamped = params.output_offset + MultiplyByQuantizedMultiplier(val - params.input_offset,
- params.output_multiplier,
- params.output_shift);
- clamped = std::max(params.quantized_activation_min, clamped);
- clamped = std::min(params.quantized_activation_max, clamped);
- output_data[i] = static_cast<T>(clamped);
- }
-}
-
-template <typename T>
-inline void ReluX(const tflite::ActivationParams &params, const RuntimeShape &input_shape,
- const T *input_data, const RuntimeShape &output_shape, T *output_data)
-{
- ruy::profiler::ScopeLabel label("Quantized ReluX (not fused)");
- const int flat_size = MatchingFlatSize(input_shape, output_shape);
- const T max_value = params.quantized_activation_max;
- const T min_value = params.quantized_activation_min;
- for (int i = 0; i < flat_size; ++i)
- {
- const T val = input_data[i];
- const T clamped = val > max_value ? max_value : val < min_value ? min_value : val;
- output_data[i] = clamped;
- }
-}
-
-// TODO(jiawen): We can implement BroadcastMul on buffers of arbitrary
-// dimensionality if the runtime code does a single loop over one dimension
-// that handles broadcasting as the base case. The code generator would then
-// generate max(D1, D2) nested for loops.
-inline void BroadcastMulFivefold(const ArithmeticParams &unswitched_params,
- const RuntimeShape &unswitched_input1_shape,
- const uint8 *unswitched_input1_data,
- const RuntimeShape &unswitched_input2_shape,
- const uint8 *unswitched_input2_data,
- const RuntimeShape &output_shape, uint8 *output_data)
-{
- ArithmeticParams switched_params = unswitched_params;
- switched_params.input1_offset = unswitched_params.input2_offset;
- switched_params.input2_offset = unswitched_params.input1_offset;
-
- const bool use_unswitched = unswitched_params.broadcast_category ==
- tflite::BroadcastableOpCategory::kFirstInputBroadcastsFast;
-
- const ArithmeticParams &params = use_unswitched ? unswitched_params : switched_params;
- const uint8 *input1_data = use_unswitched ? unswitched_input1_data : unswitched_input2_data;
- const uint8 *input2_data = use_unswitched ? unswitched_input2_data : unswitched_input1_data;
-
- // Fivefold nested loops. The second input resets its position for each
- // iteration of the second loop. The first input resets its position at the
- // beginning of the fourth loop. The innermost loop is an elementwise Mul of
- // sections of the arrays.
- uint8 *output_data_ptr = output_data;
- const uint8 *input1_data_ptr = input1_data;
- const uint8 *input2_data_reset = input2_data;
- int y0 = params.broadcast_shape[0];
- int y1 = params.broadcast_shape[1];
- int y2 = params.broadcast_shape[2];
- int y3 = params.broadcast_shape[3];
- int y4 = params.broadcast_shape[4];
- for (int i0 = 0; i0 < y0; ++i0)
- {
- const uint8 *input2_data_ptr;
- for (int i1 = 0; i1 < y1; ++i1)
- {
- input2_data_ptr = input2_data_reset;
- for (int i2 = 0; i2 < y2; ++i2)
- {
- for (int i3 = 0; i3 < y3; ++i3)
- {
- MulElementwise(y4, params, input1_data_ptr, input2_data_ptr, output_data_ptr);
- input2_data_ptr += y4;
- output_data_ptr += y4;
- }
- input1_data_ptr += y4;
- }
- }
- input2_data_reset = input2_data_ptr;
- }
-}
-
-inline void Mul(const ArithmeticParams &params, const RuntimeShape &input1_shape,
- const int16 *input1_data, const RuntimeShape &input2_shape,
- const int16 *input2_data, const RuntimeShape &output_shape, int16 *output_data)
-{
- ruy::profiler::ScopeLabel label("Mul/Int16");
-
- const int flat_size = MatchingElementsSize(input1_shape, input2_shape, output_shape);
-
- for (int i = 0; i < flat_size; i++)
- {
- // F0 uses 0 integer bits, range [-1, 1].
- using F0 = gemmlowp::FixedPoint<std::int16_t, 0>;
-
- F0 unclamped_result = F0::FromRaw(input1_data[i]) * F0::FromRaw(input2_data[i]);
- output_data[i] = unclamped_result.raw();
- }
-}
-
-inline void Mul(const ArithmeticParams &params, const RuntimeShape &input1_shape,
- const int16 *input1_data, const RuntimeShape &input2_shape,
- const int16 *input2_data, const RuntimeShape &output_shape, uint8 *output_data)
-{
- ruy::profiler::ScopeLabel label("Mul/Int16Uint8");
- int32 output_offset = params.output_offset;
- int32 output_activation_min = params.quantized_activation_min;
- int32 output_activation_max = params.quantized_activation_max;
- TFLITE_DCHECK_LE(output_activation_min, output_activation_max);
-
- const int flat_size = MatchingElementsSize(input1_shape, input2_shape, output_shape);
-
- for (int i = 0; i < flat_size; i++)
- {
- // F0 uses 0 integer bits, range [-1, 1].
- using F0 = gemmlowp::FixedPoint<std::int16_t, 0>;
-
- F0 unclamped_result = F0::FromRaw(input1_data[i]) * F0::FromRaw(input2_data[i]);
- int16 rescaled_result = gemmlowp::RoundingDivideByPOT(unclamped_result.raw(), 8);
- int16 clamped_result = std::min<int16>(output_activation_max - output_offset, rescaled_result);
- clamped_result = std::max<int16>(output_activation_min - output_offset, clamped_result);
- output_data[i] = output_offset + clamped_result;
- }
-}
-
-inline void Sub16(const ArithmeticParams &params, const RuntimeShape &input1_shape,
- const int16_t *input1_data, const RuntimeShape &input2_shape,
- const int16_t *input2_data, const RuntimeShape &output_shape,
- int16_t *output_data)
-{
- ruy::profiler::ScopeLabel label("Sub/Int16");
- const int input1_shift = params.input1_shift;
- const int flat_size = MatchingElementsSize(input1_shape, input2_shape, output_shape);
- const int16 output_activation_min = params.quantized_activation_min;
- const int16 output_activation_max = params.quantized_activation_max;
-
- TFLITE_DCHECK(input1_shift == 0 || params.input2_shift == 0);
- TFLITE_DCHECK_LE(input1_shift, 0);
- TFLITE_DCHECK_LE(params.input2_shift, 0);
- const int16 *not_shift_input = input1_shift == 0 ? input1_data : input2_data;
- const int16 *shift_input = input1_shift == 0 ? input2_data : input1_data;
- const int input_right_shift = input1_shift == 0 ? -params.input2_shift : -input1_shift;
-
- if (input1_shift == 0)
- {
- // F0 uses 0 integer bits, range [-1, 1].
- using F0 = gemmlowp::FixedPoint<std::int16_t, 0>;
- for (int i = 0; i < flat_size; ++i)
- {
- F0 input_ready_scaled = F0::FromRaw(not_shift_input[i]);
- F0 scaled_input =
- F0::FromRaw(gemmlowp::RoundingDivideByPOT(shift_input[i], input_right_shift));
- F0 result = SaturatingSub(input_ready_scaled, scaled_input);
- const int16 raw_output = result.raw();
- const int16 clamped_output =
- std::min(output_activation_max, std::max(output_activation_min, raw_output));
- output_data[i] = clamped_output;
- }
- }
- else
- {
- // F0 uses 0 integer bits, range [-1, 1].
- using F0 = gemmlowp::FixedPoint<std::int16_t, 0>;
- for (int i = 0; i < flat_size; ++i)
- {
- F0 input_ready_scaled = F0::FromRaw(not_shift_input[i]);
- F0 scaled_input =
- F0::FromRaw(gemmlowp::RoundingDivideByPOT(shift_input[i], input_right_shift));
- F0 result = SaturatingSub(scaled_input, input_ready_scaled);
- const int16 raw_output = result.raw();
- const int16 clamped_output =
- std::min(output_activation_max, std::max(output_activation_min, raw_output));
- output_data[i] = clamped_output;
- }
- }
-}
-
-template <typename Scalar>
-void Pack(const PackParams &params, const RuntimeShape *const *input_shapes,
- const Scalar *const *input_data, const RuntimeShape &output_shape, Scalar *output_data)
-{
- ruy::profiler::ScopeLabel label("Pack");
- const int dimensions = output_shape.DimensionsCount();
- int axis = params.axis;
- int inputs_count = params.inputs_count;
-
- int outer_size = 1;
- for (int i = 0; i < axis; i++)
- {
- outer_size *= output_shape.Dims(i);
- }
- int copy_size = 1;
- for (int i = params.axis + 1; i < dimensions; i++)
- {
- copy_size *= output_shape.Dims(i);
- }
- TFLITE_DCHECK_EQ((**input_shapes).FlatSize(), copy_size * outer_size);
-
- for (int i = 0; i < inputs_count; ++i)
- {
- for (int k = 0; k < outer_size; k++)
- {
- const Scalar *input_ptr = input_data[i] + copy_size * k;
- int loc = k * inputs_count * copy_size + i * copy_size;
- memcpy(output_data + loc, input_ptr, copy_size * sizeof(Scalar));
- }
- }
-}
-
-template <typename Scalar>
-void Unpack(const UnpackParams &params, const RuntimeShape &input_shape, const Scalar *input_data,
- const RuntimeShape &output_shape, Scalar *const *output_datas)
-{
- ruy::profiler::ScopeLabel label("Unpack");
- const int dimensions = input_shape.DimensionsCount();
- const int outputs_count = params.num_split;
-
- int outer_size = 1;
- int axis = params.axis;
- if (axis < 0)
- {
- axis += dimensions;
- }
- TFLITE_DCHECK_GE(axis, 0);
- TFLITE_DCHECK_LT(axis, dimensions);
- for (int i = 0; i < axis; ++i)
- {
- outer_size *= input_shape.Dims(i);
- }
- int copy_size = 1;
- for (int i = axis + 1; i < dimensions; ++i)
- {
- copy_size *= input_shape.Dims(i);
- }
- TFLITE_DCHECK_EQ(output_shape.FlatSize(), copy_size * outer_size);
-
- for (int i = 0; i < outputs_count; ++i)
- {
- for (int k = 0; k < outer_size; k++)
- {
- Scalar *output_ptr = output_datas[i] + copy_size * k;
- int loc = k * outputs_count * copy_size + i * copy_size;
- memcpy(output_ptr, input_data + loc, copy_size * sizeof(Scalar));
- }
- }
-}
-
-template <typename Scalar>
-void PackWithScaling(const PackParams &params, const RuntimeShape *const *input_shapes,
- const uint8 *const *input_data, const RuntimeShape &output_shape,
- uint8 *output_data)
-{
- ruy::profiler::ScopeLabel label("PackWithScaling");
- const int dimensions = output_shape.DimensionsCount();
- int axis = params.axis;
- const int32 *input_zeropoint = params.input_zeropoint;
- const float *input_scale = params.input_scale;
- int inputs_count = params.inputs_count;
- const int32 output_zeropoint = params.output_zeropoint;
- const float output_scale = params.output_scale;
-
- int outer_size = 1;
- for (int i = 0; i < axis; i++)
- {
- outer_size *= output_shape.Dims(i);
- }
- int copy_size = 1;
- for (int i = axis + 1; i < dimensions; i++)
- {
- copy_size *= output_shape.Dims(i);
- }
- TFLITE_DCHECK_EQ((**input_shapes).FlatSize(), copy_size * outer_size);
-
- Scalar *output_ptr = output_data;
- const float inverse_output_scale = 1.f / output_scale;
- for (int k = 0; k < outer_size; k++)
- {
- for (int i = 0; i < inputs_count; ++i)
- {
- if (input_zeropoint[i] == output_zeropoint && input_scale[i] == output_scale)
- {
- memcpy(output_ptr, input_data[i] + k * copy_size, copy_size * sizeof(Scalar));
- }
- else
- {
- assert(false);
- const float scale = input_scale[i] * inverse_output_scale;
- const float bias = -input_zeropoint[i] * scale;
- auto input_ptr = input_data[i];
- for (int j = 0; j < copy_size; ++j)
- {
- const int value =
- static_cast<int32_t>(std::round(input_ptr[j] * scale + bias)) + output_zeropoint;
- output_ptr[j] = static_cast<uint8_t>(std::max(std::min(255, value), 0));
- }
- }
- output_ptr += copy_size;
- }
- }
-}
-
-template <typename Scalar>
-void DepthConcatenation(const ConcatenationParams &params, const RuntimeShape *const *input_shapes,
- const Scalar *const *input_data, const RuntimeShape &output_shape,
- Scalar *output_data)
-{
- ruy::profiler::ScopeLabel label("DepthConcatenation");
- auto params_copy = params;
- params_copy.axis = 3;
- Concatenation(params_copy, input_shapes, input_data, output_shape, output_data);
-}
-
-inline void LstmCell(const LstmCellParams &params, const RuntimeShape &unextended_input_shape,
- const float *input_data, const RuntimeShape &unextended_prev_activ_shape,
- const float *prev_activ_data, const RuntimeShape &weights_shape,
- const float *weights_data, const RuntimeShape &unextended_bias_shape,
- const float *bias_data, const RuntimeShape &unextended_prev_state_shape,
- const float *prev_state_data,
- const RuntimeShape &unextended_output_state_shape, float *output_state_data,
- const RuntimeShape &unextended_output_activ_shape, float *output_activ_data,
- const RuntimeShape &unextended_concat_temp_shape, float *concat_temp_data,
- const RuntimeShape &unextended_activ_temp_shape, float *activ_temp_data)
-{
- TFLITE_DCHECK_LE(unextended_input_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_prev_activ_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_bias_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_prev_state_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_output_state_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_output_activ_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_concat_temp_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_activ_temp_shape.DimensionsCount(), 4);
- const RuntimeShape input_shape = RuntimeShape::ExtendedShape(4, unextended_input_shape);
- const RuntimeShape prev_activ_shape = RuntimeShape::ExtendedShape(4, unextended_prev_activ_shape);
- const RuntimeShape bias_shape = RuntimeShape::ExtendedShape(4, unextended_bias_shape);
- const RuntimeShape prev_state_shape = RuntimeShape::ExtendedShape(4, unextended_prev_state_shape);
- const RuntimeShape output_state_shape =
- RuntimeShape::ExtendedShape(4, unextended_output_state_shape);
- const RuntimeShape output_activ_shape =
- RuntimeShape::ExtendedShape(4, unextended_output_activ_shape);
- const RuntimeShape concat_temp_shape =
- RuntimeShape::ExtendedShape(4, unextended_concat_temp_shape);
- const RuntimeShape activ_temp_shape = RuntimeShape::ExtendedShape(4, unextended_activ_temp_shape);
- TFLITE_DCHECK_GE(weights_shape.DimensionsCount(), 2);
-
- const int weights_dim_count = weights_shape.DimensionsCount();
- const int batches = MatchingDim(input_shape, 0, prev_activ_shape, 0, prev_state_shape, 0,
- output_state_shape, 0, output_activ_shape, 0);
- const int height = MatchingDim(input_shape, 1, prev_activ_shape, 1, prev_state_shape, 1,
- output_state_shape, 1, output_activ_shape, 1);
- const int width = MatchingDim(input_shape, 2, prev_activ_shape, 2, prev_state_shape, 2,
- output_state_shape, 2, output_activ_shape, 2);
- const int input_depth = input_shape.Dims(3);
- const int prev_activ_depth = prev_activ_shape.Dims(3);
- const int total_input_depth = prev_activ_depth + input_depth;
- TFLITE_DCHECK_EQ(weights_shape.Dims(weights_dim_count - 1), total_input_depth);
- TFLITE_DCHECK_EQ(FlatSizeSkipDim(bias_shape, 3), 1);
- const int intern_activ_depth = MatchingDim(weights_shape, weights_dim_count - 2, bias_shape, 3);
- TFLITE_DCHECK_EQ(weights_shape.FlatSize(), intern_activ_depth * total_input_depth);
- TFLITE_DCHECK_EQ(intern_activ_depth % 4, 0);
- const int output_depth = MatchingDim(prev_state_shape, 3, prev_activ_shape, 3, output_state_shape,
- 3, output_activ_shape, 3);
- TFLITE_DCHECK_EQ(output_depth, intern_activ_depth / 4);
-
- // Concatenate prev_activ and input data together
- std::vector<float const *> concat_input_arrays_data;
- std::vector<RuntimeShape const *> concat_input_arrays_shapes;
- concat_input_arrays_data.push_back(input_data);
- concat_input_arrays_data.push_back(prev_activ_data);
- concat_input_arrays_shapes.push_back(&input_shape);
- concat_input_arrays_shapes.push_back(&prev_activ_shape);
- tflite::ConcatenationParams concat_params;
- concat_params.axis = 3;
- concat_params.inputs_count = concat_input_arrays_data.size();
- Concatenation(concat_params, &(concat_input_arrays_shapes[0]), &(concat_input_arrays_data[0]),
- concat_temp_shape, concat_temp_data);
-
- // Fully connected
- tflite::FullyConnectedParams fc_params;
- fc_params.float_activation_min = std::numeric_limits<float>::lowest();
- fc_params.float_activation_max = std::numeric_limits<float>::max();
- FullyConnected(fc_params, concat_temp_shape, concat_temp_data, weights_shape, weights_data,
- bias_shape, bias_data, activ_temp_shape, activ_temp_data);
-
- // Memory state update (the LSTM "guts")
- for (int b = 0; b < batches; ++b)
- {
- for (int w = 0; w < width; ++w)
- {
- for (int h = 0; h < height; ++h)
- {
- for (int c = 0; c < output_depth; ++c)
- {
- const float input_gate =
- 1.f /
- (1.f +
- std::exp(-activ_temp_data[Offset(activ_temp_shape, b, h, w, 0 * output_depth + c)]));
- const float new_input =
- std::tanh(activ_temp_data[Offset(activ_temp_shape, b, h, w, 1 * output_depth + c)]);
- const float forget_gate =
- 1.f /
- (1.f +
- std::exp(-activ_temp_data[Offset(activ_temp_shape, b, h, w, 2 * output_depth + c)]));
- const float output_gate =
- 1.f /
- (1.f +
- std::exp(-activ_temp_data[Offset(activ_temp_shape, b, h, w, 3 * output_depth + c)]));
- const float new_state =
- input_gate * new_input +
- forget_gate * prev_state_data[Offset(prev_state_shape, b, h, w, c)];
- output_state_data[Offset(output_state_shape, b, h, w, c)] = new_state;
- output_activ_data[Offset(output_activ_shape, b, h, w, c)] =
- output_gate * std::tanh(new_state);
- }
- }
- }
- }
-}
-
-// Quantized LSTM cell implementation.
-// The quantization of the input, output arrays is as follows:
-// - The input activations are quantized as uint8 on the interval
-// [-1, 127/128].
-// The rationale for that is that is the natural interval for output
-// activations (see next point) and these need to be concatenated together.
-// We could accommodate different ranges by re-scaling, but we empirically
-// found that setting the input activations range to be [-1, 127/128] in the
-// first place, removing the need for re-scaling, greatly improves accuracy.
-// - The output activations are quantized as uint8 on the interval
-// [-1, 127/128].
-// The rationale for that is that the definition of a LSTM cell makes them
-// intrinsically constrained in [-1, 1]; tweaking that to [-1, 127/128]
-// makes for simpler, more accurate fixed-point arithmetic.
-// - The output-at-previous-timestep state array is obviously quantized as
-// the output activations.
-// - The internal LSTM memory (not the output-at-previous-timestep, the other
-// internal state array) is int16-quantized and may use any power-of-two,
-// symmetric range i.e. [-2^N, 2^N * 32767/32768] for any N, which we call
-// StateIntegerBits below, see the below discussion of that template
-// parameter ("The StateIntegerBits template parameter").
-// - The output of the internal fully-connected node is int16-quantized
-// on the interval [-8, 8 * 32767/32768], the rationale for which is
-// explained just below ("Why [-8, 8] for fully-connected output?").
-//
-//
-// === The StateIntegerBits template parameter ===
-//
-// The StateIntegerBits template parameter controls the fixed-point format used
-// to represent the internal memory of the LSTM cell (not the
-// output-at-previous-timestep, the other internal state array). It's currently
-// a template parameter so that the model can control that. The most typical
-// value for StateIntegerBits is 4. Other plausible values are anywhere between
-// 3 and 5. We might eventually standardize on a single supported value, e.g. 4,
-// and drop that template parameter. The reason why it can't be a runtime
-// parameter is that this controls the fixed-point format used, i.e. we need to
-// generate actually different code based on it. In particular, we generate code
-// for a fixed-point tanh() implementation for that format, which internally
-// uses a fixed-point exp() implementation, which internally uses a
-// barrel-shifter with a number of steps that depends on StateIntegerBits.
-// Another consequence of that is that a higher value of StateIntegerBits
-// results in a more expensive implementation (more barrel shifter steps
-// needed).
-//
-//
-// === Why [-8, 8] for fully-connected output? ===
-//
-// This array is only fed to Logistic and Tanh functions, for which
-// the quantized implementation will want to use fixed-point arithmetic,
-// requiring a power-of-two representation interval. Thus, we should right
-// away quantize this array to a power-of-two interval; otherwise,
-// implementation will need to rescale that, losing any benefit that a tighter
-// representation interval might otherwise yield, while introducing some
-// numerical error and computational overhead.
-//
-// Now, Logistic and Tanh
-// are nearly constant (nearly equal to their horizontal asymptotes)
-// outside of a small bounded interval around 0:
-//
-// Logistic(4) = 1 - 1.8e-2 Tanh(4) = 1 - 6.7e-4
-// Logistic(8) = 1 - 3.4e-4 Tanh(8) = 1 - 2.3e-7
-// Logistic(16) = 1 - 1.1e-7 Tanh(16) = 1 - 2.5e-14
-//
-// From this, we see that clamping to [-4, 4] would be too inaccurate
-// (the error of 1.8e-2 on Logistic would be felt even in 8bit precision)
-// while clamping to [-16, 16] would make no difference even in float32.
-// However, for a fixed-point implementation in 16-bit integers, using 5
-// integer bits to represent the [-16, 16] range would leave only 11
-// fractional bits, giving an increment of 2^-11 = 4.9e-4 between consecutive
-// representable values. Notice that is higher than the
-// worst-case clamping error with clamping to [-8, 8]: 3.4e-4 for Logistic.
-// Using [-8, 8] thus seems like the better compromise overall, enjoying
-// an increment of 2.4e-4 between representable values and a worst-case
-// clamping error of 3.4e-4, both better than the increment of 4.9e-4 with
-// [-16, 16].
-//
-// Moreover, all other things being equal, it is nice to choose the narrower
-// representation range, as that makes the implementation of fixed-point
-// math functions a little cheaper (each integer bit requires an additional
-// barrel-shifter atep in the implementation of exp(-x)). That is further
-// reason to prefer [-8, 8] over [-16, 16]. The choice of [-16, 16] would make
-// sense for 32-bit float or 32-bit fixed-point quantization, but we are
-// aiming for 16-bit fixed-point quantization of these internal nodes here.
-//
-template <int StateIntegerBits>
-inline void
-LstmCell(const LstmCellParams &params, const RuntimeShape &unextended_input_shape,
- const uint8 *input_data_uint8, const RuntimeShape &unextended_prev_activ_shape,
- const uint8 *prev_activ_data_uint8, const RuntimeShape &weights_shape,
- const uint8 *weights_data_uint8, const RuntimeShape &unextended_bias_shape,
- const int32 *bias_data_int32, const RuntimeShape &unextended_prev_state_shape,
- const int16 *prev_state_data_int16, const RuntimeShape &unextended_output_state_shape,
- int16 *output_state_data_int16, const RuntimeShape &unextended_output_activ_shape,
- uint8 *output_activ_data_uint8, const RuntimeShape &unextended_concat_temp_shape,
- uint8 *concat_temp_data_uint8, const RuntimeShape &unextended_activ_temp_shape,
- int16 *activ_temp_data_int16, void *gemmlowp_context)
-{
- (void)gemmlowp_context; // only used in optimized code.
- int32 weights_zero_point = params.weights_zero_point;
- int32 accum_multiplier = params.accum_multiplier;
- int accum_shift = params.accum_shift;
- TFLITE_DCHECK_LE(unextended_input_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_prev_activ_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_bias_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_prev_state_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_output_state_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_output_activ_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_concat_temp_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_activ_temp_shape.DimensionsCount(), 4);
- const RuntimeShape input_shape = RuntimeShape::ExtendedShape(4, unextended_input_shape);
- const RuntimeShape prev_activ_shape = RuntimeShape::ExtendedShape(4, unextended_prev_activ_shape);
- const RuntimeShape bias_shape = RuntimeShape::ExtendedShape(4, unextended_bias_shape);
- const RuntimeShape prev_state_shape = RuntimeShape::ExtendedShape(4, unextended_prev_state_shape);
- const RuntimeShape output_state_shape =
- RuntimeShape::ExtendedShape(4, unextended_output_state_shape);
- const RuntimeShape output_activ_shape =
- RuntimeShape::ExtendedShape(4, unextended_output_activ_shape);
- const RuntimeShape concat_temp_shape =
- RuntimeShape::ExtendedShape(4, unextended_concat_temp_shape);
- const RuntimeShape activ_temp_shape = RuntimeShape::ExtendedShape(4, unextended_activ_temp_shape);
- TFLITE_DCHECK_GE(weights_shape.DimensionsCount(), 2);
-
- // Gather dimensions information, and perform consistency checks.
- const int weights_dim_count = weights_shape.DimensionsCount();
- const int outer_size = MatchingFlatSizeSkipDim(input_shape, 3, prev_activ_shape, prev_state_shape,
- output_state_shape, output_activ_shape);
- const int input_depth = input_shape.Dims(3);
- const int prev_activ_depth = prev_activ_shape.Dims(3);
- const int total_input_depth = prev_activ_depth + input_depth;
- TFLITE_DCHECK_EQ(weights_shape.Dims(weights_dim_count - 1), total_input_depth);
- const int intern_activ_depth = MatchingDim(weights_shape, weights_dim_count - 2, bias_shape, 3);
- TFLITE_DCHECK_EQ(weights_shape.FlatSize(), intern_activ_depth * total_input_depth);
- TFLITE_DCHECK_EQ(FlatSizeSkipDim(bias_shape, 3), 1);
- TFLITE_DCHECK_EQ(intern_activ_depth % 4, 0);
- const int output_depth = MatchingDim(prev_state_shape, 3, prev_activ_shape, 3, output_state_shape,
- 3, output_activ_shape, 3);
- TFLITE_DCHECK_EQ(output_depth, intern_activ_depth / 4);
- const int fc_batches = FlatSizeSkipDim(activ_temp_shape, 3);
- const int fc_output_depth =
- MatchingDim(weights_shape, weights_dim_count - 2, activ_temp_shape, 3);
- const int fc_accum_depth = total_input_depth;
- TFLITE_DCHECK_EQ(fc_output_depth, 4 * output_depth);
-
- // Depth-concatenate prev_activ and input data together.
- uint8 const *concat_input_arrays_data[2] = {input_data_uint8, prev_activ_data_uint8};
- const RuntimeShape *concat_input_arrays_shapes[2] = {&input_shape, &prev_activ_shape};
- tflite::ConcatenationParams concat_params;
- concat_params.axis = 3;
- concat_params.inputs_count = 2;
- Concatenation(concat_params, concat_input_arrays_shapes, concat_input_arrays_data,
- concat_temp_shape, concat_temp_data_uint8);
-
- // Implementation of the fully connected node inside the LSTM cell.
- // The operands are 8-bit integers, the accumulators are internally 32bit
- // integers, and the output is 16-bit fixed-point with 3 integer bits so
- // the output range is [-2^3, 2^3] == [-8, 8]. The rationale for that
- // is explained in the function comment above.
- for (int b = 0; b < fc_batches; ++b)
- {
- for (int out_c = 0; out_c < fc_output_depth; ++out_c)
- {
- // Internal accumulation.
- // Initialize accumulator with the bias-value.
- int32 accum = bias_data_int32[out_c];
- // Accumulation loop.
- for (int d = 0; d < fc_accum_depth; ++d)
- {
- int16 input_val = concat_temp_data_uint8[b * fc_accum_depth + d] - 128;
- int16 weights_val = weights_data_uint8[out_c * fc_accum_depth + d] - weights_zero_point;
- accum += input_val * weights_val;
- }
- // Down-scale the final int32 accumulator to the scale used by our
- // (16-bit, using 3 integer bits) fixed-point format. The quantized
- // multiplier and shift here have been pre-computed offline
- // (e.g. by toco).
- accum = MultiplyByQuantizedMultiplier(accum, accum_multiplier, accum_shift);
- // Saturate, cast to int16, and store to the temporary activations array.
- accum = std::max(-32768, std::min(32767, static_cast<int>(accum)));
- activ_temp_data_int16[out_c + fc_output_depth * b] = accum;
- }
- }
-
- // Rest of the LSTM cell: tanh and logistic math functions, and some adds
- // and muls, all done in 16-bit fixed-point.
- for (int b = 0; b < outer_size; ++b)
- {
- for (int c = 0; c < output_depth; ++c)
- {
- // Define the fixed-point data types that we will use here. All use
- // int16 as the underlying integer type i.e. all are 16-bit fixed-point.
- // They only differ by the number of integral vs. fractional bits,
- // determining the range of values that they can represent.
- //
- // F0 uses 0 integer bits, range [-1, 1].
- // This is the return type of math functions such as tanh, logistic,
- // whose range is in [-1, 1].
- using F0 = gemmlowp::FixedPoint<std::int16_t, 0>;
- // F3 uses 3 integer bits, range [-8, 8].
- // This is the range of the previous fully-connected node's output,
- // which is our input here.
- using F3 = gemmlowp::FixedPoint<std::int16_t, 3>;
- // FS uses StateIntegerBits integer bits, range [-2^StateIntegerBits,
- // 2^StateIntegerBits]. It's used to represent the internal state, whose
- // number of integer bits is currently dictated by the model. See comment
- // on the StateIntegerBits template parameter above.
- using FS = gemmlowp::FixedPoint<std::int16_t, StateIntegerBits>;
- // Implementation of input gate, using fixed-point logistic function.
- F3 input_gate_input =
- F3::FromRaw(activ_temp_data_int16[b * fc_output_depth + 0 * output_depth + c]);
- F0 input_gate_output = gemmlowp::logistic(input_gate_input);
- // Implementation of input modulation gate, using fixed-point tanh
- // function.
- F3 input_modulation_gate_input =
- F3::FromRaw(activ_temp_data_int16[b * fc_output_depth + 1 * output_depth + c]);
- F0 input_modulation_gate_output = gemmlowp::tanh(input_modulation_gate_input);
- // Implementation of forget gate, using fixed-point logistic function.
- F3 forget_gate_input =
- F3::FromRaw(activ_temp_data_int16[b * fc_output_depth + 2 * output_depth + c]);
- F0 forget_gate_output = gemmlowp::logistic(forget_gate_input);
- // Implementation of output gate, using fixed-point logistic function.
- F3 output_gate_input =
- F3::FromRaw(activ_temp_data_int16[b * fc_output_depth + 3 * output_depth + c]);
- F0 output_gate_output = gemmlowp::logistic(output_gate_input);
- // Implementation of internal multiplication nodes, still in fixed-point.
- F0 input_times_input_modulation = input_gate_output * input_modulation_gate_output;
- FS prev_state = FS::FromRaw(prev_state_data_int16[b * output_depth + c]);
- FS prev_state_times_forget_state = forget_gate_output * prev_state;
- // Implementation of internal addition node, saturating.
- FS new_state =
- gemmlowp::SaturatingAdd(gemmlowp::Rescale<StateIntegerBits>(input_times_input_modulation),
- prev_state_times_forget_state);
- // Implementation of last internal Tanh node, still in fixed-point.
- // Since a Tanh fixed-point implementation is specialized for a given
- // number or integer bits, and each specialization can have a substantial
- // code size, and we already used above a Tanh on an input with 3 integer
- // bits, and per the table in the above function comment there is no
- // significant accuracy to be lost by clamping to [-8, +8] for a
- // 3-integer-bits representation, let us just do that. This helps people
- // porting this to targets where code footprint must be minimized.
- F3 new_state_f3 = gemmlowp::Rescale<3>(new_state);
- F0 output_activ_int16 = output_gate_output * gemmlowp::tanh(new_state_f3);
- // Store the new internal state back to memory, as 16-bit integers.
- // Note: here we store the original value with StateIntegerBits, not
- // the rescaled 3-integer-bits value fed to tanh.
- output_state_data_int16[b * output_depth + c] = new_state.raw();
- // Down-scale the output activations to 8-bit integers, saturating,
- // and store back to memory.
- int16 rescaled_output_activ = gemmlowp::RoundingDivideByPOT(output_activ_int16.raw(), 8);
- int16 clamped_output_activ =
- std::max<int16>(-128, std::min<int16>(127, rescaled_output_activ));
- output_activ_data_uint8[b * output_depth + c] = 128 + clamped_output_activ;
- }
- }
-}
-
-template <typename Scalar>
-void Split(const SplitParams &params, const RuntimeShape &input_shape, const Scalar *input_data,
- const RuntimeShape *const *output_shapes, Scalar *const *output_data)
-{
- ruy::profiler::ScopeLabel label("Split");
- const int split_dimensions = input_shape.DimensionsCount();
- int axis = params.axis < 0 ? params.axis + split_dimensions : params.axis;
- int outputs_count = params.num_split;
- TFLITE_DCHECK_LT(axis, split_dimensions);
-
- int64_t split_size = 0;
- for (int i = 0; i < outputs_count; i++)
- {
- TFLITE_DCHECK_EQ(output_shapes[i]->DimensionsCount(), split_dimensions);
- for (int j = 0; j < split_dimensions; j++)
- {
- if (j != axis)
- {
- MatchingDim(*output_shapes[i], j, input_shape, j);
- }
- }
- split_size += output_shapes[i]->Dims(axis);
- }
- TFLITE_DCHECK_EQ(split_size, input_shape.Dims(axis));
- int64_t outer_size = 1;
- for (int i = 0; i < axis; ++i)
- {
- outer_size *= input_shape.Dims(i);
- }
- // For all output arrays,
- // FlatSize() = outer_size * Dims(axis) * base_inner_size;
- int64_t base_inner_size = 1;
- for (int i = axis + 1; i < split_dimensions; ++i)
- {
- base_inner_size *= input_shape.Dims(i);
- }
-
- const Scalar *input_ptr = input_data;
- for (int k = 0; k < outer_size; k++)
- {
- for (int i = 0; i < outputs_count; ++i)
- {
- const int copy_size = output_shapes[i]->Dims(axis) * base_inner_size;
- memcpy(output_data[i] + k * copy_size, input_ptr, copy_size * sizeof(Scalar));
- input_ptr += copy_size;
- }
- }
-}
-
-inline int NodeOffset(int b, int h, int w, int height, int width)
-{
- return (b * height + h) * width + w;
-}
-
-inline void LocalResponseNormalization(const tflite::LocalResponseNormalizationParams &op_params,
- const RuntimeShape &input_shape, const float *input_data,
- const RuntimeShape &output_shape, float *output_data)
-{
- const int trailing_dim = input_shape.DimensionsCount() - 1;
- const int outer_size = MatchingFlatSizeSkipDim(input_shape, trailing_dim, output_shape);
- const int depth = MatchingDim(input_shape, trailing_dim, output_shape, trailing_dim);
-
- for (int i = 0; i < outer_size; ++i)
- {
- for (int c = 0; c < depth; ++c)
- {
- const int begin_input_c = std::max(0, static_cast<int>(c - op_params.range));
- const int end_input_c = std::min(depth, static_cast<int>(c + op_params.range));
- float accum = 0.f;
- for (int input_c = begin_input_c; input_c < end_input_c; ++input_c)
- {
- const float input_val = input_data[i * depth + input_c];
- accum += input_val * input_val;
- }
- const float multiplier = std::pow(op_params.bias + op_params.alpha * accum, -op_params.beta);
- output_data[i * depth + c] = input_data[i * depth + c] * multiplier;
- }
- }
-}
-
-inline void Dequantize(const RuntimeShape &input_shape, const Eigen::half *input_data,
- const RuntimeShape &output_shape, float *output_data)
-{
- const int flat_size = MatchingFlatSize(input_shape, output_shape);
- for (int i = 0; i < flat_size; i++)
- {
- output_data[i] = static_cast<float>(input_data[i]);
- }
-}
-
-inline void FakeQuant(const tflite::FakeQuantParams &op_params, const RuntimeShape &input_shape,
- const float *input_data, const RuntimeShape &output_shape, float *output_data)
-{
- ruy::profiler::ScopeLabel label("FakeQuant");
- float rmin = op_params.minmax.min;
- float rmax = op_params.minmax.max;
- int num_bits = op_params.num_bits;
- // 0 should always be a representable value. Let's assume that the initial
- // min,max range contains 0.
- TFLITE_DCHECK_LE(rmin, 0.0f);
- TFLITE_DCHECK_GE(rmax, 0.0f);
- TFLITE_DCHECK_LT(rmin, rmax);
-
- // Code matches tensorflow's FakeQuantWithMinMaxArgsFunctor.
- int quant_min = 0;
- int quant_max = (1 << num_bits) - 1;
- float nudged_min, nudged_max, nudged_scale;
- NudgeQuantizationRange(rmin, rmax, quant_min, quant_max, &nudged_min, &nudged_max, &nudged_scale);
- const int flat_size = MatchingFlatSize(input_shape, output_shape);
- FakeQuantizeArray(nudged_scale, nudged_min, nudged_max, input_data, output_data, flat_size);
-}
-
-// Common subroutine for both `GatherNd` and `GatherNdString`.
-struct GatherNdHelperResult
-{
- int n_slices;
- int slice_size;
- int indices_nd;
- std::vector<int> dims_to_count;
-};
-
-// Returns common values being used on both `GatherNd` and `GatherNdString`.
-inline GatherNdHelperResult GatherNdHelper(const RuntimeShape &params_shape,
- const RuntimeShape &indices_shape)
-{
- GatherNdHelperResult ret;
- ret.n_slices = 1;
- ret.slice_size = 1;
- const int indices_dims = indices_shape.DimensionsCount();
- ret.indices_nd = indices_shape.Dims(indices_dims - 1);
- const int params_dims = params_shape.DimensionsCount();
- for (int i = 0; i < indices_dims - 1; ++i)
- {
- ret.n_slices *= indices_shape.Dims(i);
- }
- for (int i = ret.indices_nd; i < params_dims; ++i)
- {
- ret.slice_size *= params_shape.Dims(i);
- }
-
- int remain_flat_size = params_shape.FlatSize();
- ret.dims_to_count = std::vector<int>(ret.indices_nd, 0);
- for (int i = 0; i < ret.indices_nd; ++i)
- {
- ret.dims_to_count[i] = remain_flat_size / params_shape.Dims(i);
- remain_flat_size = ret.dims_to_count[i];
- }
-
- return ret;
-}
-
-template <typename ParamsT, typename IndicesT = int32>
-inline void GatherNd(const RuntimeShape &params_shape, const ParamsT *params_data,
- const RuntimeShape &indices_shape, const IndicesT *indices_data,
- const RuntimeShape &output_shape, ParamsT *output_data)
-{
- ruy::profiler::ScopeLabel label("GatherNd");
-
- const GatherNdHelperResult res = GatherNdHelper(params_shape, indices_shape);
- for (int i = 0; i < res.n_slices; ++i)
- {
- int from_pos = 0;
- for (int j = 0; j < res.indices_nd; ++j)
- {
- from_pos += indices_data[i * res.indices_nd + j] * res.dims_to_count[j];
- }
- std::memcpy(output_data + i * res.slice_size, params_data + from_pos,
- sizeof(ParamsT) * res.slice_size);
- }
-}
-
-#ifndef TF_LITE_STATIC_MEMORY
-template <typename IndicesT = int32>
-inline void GatherNdString(const RuntimeShape &params_shape, const TfLiteTensor *params_data,
- const RuntimeShape &indices_shape, const IndicesT *indices_data,
- const RuntimeShape &output_shape, TfLiteTensor *output_data)
-{
- ruy::profiler::ScopeLabel label("GatherNdString");
-
- const GatherNdHelperResult res = GatherNdHelper(params_shape, indices_shape);
- DynamicBuffer buffer;
- for (int i = 0; i < res.n_slices; ++i)
- {
- int from_pos = 0;
- for (int j = 0; j < res.indices_nd; ++j)
- {
- from_pos += indices_data[i * res.indices_nd + j] * res.dims_to_count[j];
- }
- for (int j = 0; j < res.slice_size; ++j)
- {
- buffer.AddString(GetString(params_data, from_pos + j));
- }
- }
- buffer.WriteToTensor(output_data, /*new_shape=*/nullptr);
-}
-#endif
-
-template <typename IndicesT, typename UpdatesT>
-inline void ScatterNd(const RuntimeShape &indices_shape, const IndicesT *indices_data,
- const RuntimeShape &updates_shape, const UpdatesT *updates_data,
- const RuntimeShape &output_shape, UpdatesT *output_data)
-{
- ruy::profiler::ScopeLabel label("ScatterNd");
-
- int n_slices = 1;
- int slice_size = 1;
- const int outer_dims = indices_shape.DimensionsCount() - 1;
- const int indices_nd = indices_shape.Dims(outer_dims);
- const int updates_dims = updates_shape.DimensionsCount();
- for (int i = 0; i < outer_dims; ++i)
- {
- n_slices *= indices_shape.Dims(i);
- }
- for (int i = outer_dims; i < updates_dims; ++i)
- {
- slice_size *= updates_shape.Dims(i);
- }
-
- int output_flat_size = output_shape.FlatSize();
- int remain_flat_size = output_flat_size;
- std::vector<int> dims_to_count(indices_nd, 0);
- for (int i = 0; i < indices_nd; ++i)
- {
- dims_to_count[i] = remain_flat_size / output_shape.Dims(i);
- remain_flat_size = dims_to_count[i];
- }
-
- memset(output_data, 0, sizeof(UpdatesT) * output_flat_size);
- for (int i = 0; i < n_slices; ++i)
- {
- int to_pos = 0;
- for (int j = 0; j < indices_nd; ++j)
- {
- IndicesT idx = indices_data[i * indices_nd + j];
- TFLITE_DCHECK(0 <= idx && idx < output_shape.Dims(j));
- to_pos += idx * dims_to_count[j];
- }
- for (int j = 0; j < slice_size; j++)
- {
- output_data[to_pos + j] += updates_data[i * slice_size + j];
- }
- }
-}
-
-template <typename T>
-inline void Slice(const tflite::SliceParams &op_params, const RuntimeShape &input_shape,
- const RuntimeShape &output_shape, SequentialTensorWriter<T> *writer)
-{
- const RuntimeShape ext_shape = RuntimeShape::ExtendedShape(5, input_shape);
- TFLITE_DCHECK_LE(op_params.begin_count, 5);
- TFLITE_DCHECK_LE(op_params.size_count, 5);
- const int begin_count = op_params.begin_count;
- const int size_count = op_params.size_count;
- // We front-pad the begin and size vectors.
- std::array<int, 5> start;
- std::array<int, 5> stop;
- for (int i = 0; i < 5; ++i)
- {
- int padded_i = 5 - i;
- start[i] = begin_count < padded_i ? 0 : op_params.begin[begin_count - padded_i];
- stop[i] = (size_count < padded_i || op_params.size[size_count - padded_i] == -1)
- ? ext_shape.Dims(i)
- : start[i] + op_params.size[size_count - padded_i];
- }
-
- for (int i0 = start[0]; i0 < stop[0]; ++i0)
- {
- for (int i1 = start[1]; i1 < stop[1]; ++i1)
- {
- for (int i2 = start[2]; i2 < stop[2]; ++i2)
- {
- for (int i3 = start[3]; i3 < stop[3]; ++i3)
- {
- for (int i4 = start[4]; i4 < stop[4]; ++i4)
- {
- writer->Write(Offset(ext_shape, i0, i1, i2, i3, i4));
- }
- }
- }
- }
- }
-}
-
-template <typename T>
-inline void Slice(const tflite::SliceParams &op_params, const RuntimeShape &input_shape,
- const T *input_data, const RuntimeShape &output_shape, T *output_data)
-{
- SequentialTensorWriter<T> writer(input_data, output_data);
- return Slice(op_params, input_shape, output_shape, &writer);
-}
-
-template <typename T>
-inline void Slice(const tflite::SliceParams &op_params, const RuntimeShape &input_shape,
- const TfLiteTensor *input, const RuntimeShape &output_shape, TfLiteTensor *output)
-{
- SequentialTensorWriter<T> writer(input, output);
- return Slice(op_params, input_shape, output_shape, &writer);
-}
-
-template <typename T>
-void Minimum(const RuntimeShape &input1_shape, const T *input1_data, const T *input2_data,
- const RuntimeShape &output_shape, T *output_data)
-{
- const int flat_size = MatchingFlatSize(input1_shape, output_shape);
-
- auto min_value = input2_data[0];
- for (int i = 0; i < flat_size; i++)
- {
- output_data[i] = input1_data[i] > min_value ? min_value : input1_data[i];
- }
-}
-
-// Convenience version that allows, for example, generated-code calls to be
-// the same as other binary ops.
-template <typename T>
-inline void Minimum(const RuntimeShape &input1_shape, const T *input1_data, const RuntimeShape &,
- const T *input2_data, const RuntimeShape &output_shape, T *output_data)
-{
- // Drop shape of second input: not needed.
- Minimum(input1_shape, input1_data, input2_data, output_shape, output_data);
-}
-
-template <typename T>
-void Maximum(const RuntimeShape &input1_shape, const T *input1_data, const T *input2_data,
- const RuntimeShape &output_shape, T *output_data)
-{
- const int flat_size = MatchingFlatSize(input1_shape, output_shape);
-
- auto max_value = input2_data[0];
- for (int i = 0; i < flat_size; i++)
- {
- output_data[i] = input1_data[i] < max_value ? max_value : input1_data[i];
- }
-}
-
-// Convenience version that allows, for example, generated-code calls to be
-// the same as other binary ops.
-template <typename T>
-inline void Maximum(const RuntimeShape &input1_shape, const T *input1_data, const RuntimeShape &,
- const T *input2_data, const RuntimeShape &output_shape, T *output_data)
-{
- // Drop shape of second input: not needed.
- Maximum(input1_shape, input1_data, input2_data, output_shape, output_data);
-}
-
-template <typename T1, typename T2, typename T3>
-void ArgMax(const RuntimeShape &input1_shape, const T1 *input1_data, const T3 *input2_data,
- const RuntimeShape &output_shape, T2 *output_data)
-{
- ArgMinMax(input1_shape, input1_data, input2_data, output_shape, output_data, std::greater<T1>());
-}
-
-// Convenience version that allows, for example, generated-code calls to be
-// the same as other binary ops.
-template <typename T1, typename T2, typename T3>
-inline void ArgMax(const RuntimeShape &input1_shape, const T1 *input1_data,
- const RuntimeShape &input2_shape, const T3 *input2_data,
- const RuntimeShape &output_shape, T2 *output_data)
-{
- // Drop shape of second input: not needed.
- ArgMax(input1_shape, input1_data, input2_data, output_shape, output_data);
-}
-
-template <typename D, typename T>
-void Select(const RuntimeShape &input_condition_shape, const D *input_condition_data,
- const RuntimeShape &input_x_shape, const T *input_x_data,
- const RuntimeShape &input_y_shape, const T *input_y_data,
- const RuntimeShape &output_shape, T *output_data)
-{
- int64_t flatsize;
- // Allow select operator executions on mixed scalar tensors and one element
- // tensors.
- if (input_condition_shape.FlatSize() == 1 && input_x_shape.FlatSize() == 1 &&
- input_y_shape.FlatSize() == 1 && output_shape.FlatSize() == 1)
- {
- flatsize = 1;
- }
- else
- {
- flatsize = MatchingFlatSize(input_condition_shape, input_x_shape, input_y_shape, output_shape);
- }
- for (int64_t i = 0; i < flatsize; ++i)
- {
- output_data[i] = input_condition_data[i] ? input_x_data[i] : input_y_data[i];
- }
-}
-
-template <typename D, typename T>
-void RankOneSelect(const RuntimeShape &input_condition_shape, const D *input_condition_data,
- const RuntimeShape &input_x_shape, const T *input_x_data,
- const RuntimeShape &input_y_shape, const T *input_y_data,
- const RuntimeShape &output_shape, T *output_data)
-{
- const int64_t outer_size = input_condition_shape.FlatSize();
- int64_t inner_size;
- if (input_condition_shape.DimensionsCount() == 0)
- {
- inner_size = MatchingFlatSize(input_x_shape, input_y_shape, output_shape);
- }
- else
- {
- TFLITE_DCHECK_EQ(MatchingDim(input_x_shape, 0, input_y_shape, 0, output_shape, 0), outer_size);
- inner_size = MatchingFlatSizeSkipDim(input_x_shape, 0, input_y_shape, output_shape);
- }
-
- int64_t offset = 0;
- for (int64_t i = 0; i < outer_size; i++)
- {
- const T *input_data = input_condition_data[i] ? input_x_data : input_y_data;
- memcpy(output_data + offset, input_data + offset, inner_size * sizeof(T));
- offset += inner_size;
- }
-}
-
-template <typename D, typename T>
-void BroadcastSelect4DSlow(const RuntimeShape &input_condition_shape, const D *input_condition_data,
- const RuntimeShape &input_x_shape, const T *input_x_data,
- const RuntimeShape &input_y_shape, const T *input_y_data,
- const RuntimeShape &output_shape, T *output_data)
-{
- TFLITE_DCHECK_LE(input_condition_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(input_x_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(input_y_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(output_shape.DimensionsCount(), 4);
-
- const RuntimeShape extended_output_shape = RuntimeShape::ExtendedShape(4, output_shape);
-
- NdArrayDesc<4> desc_condition;
- NdArrayDesc<4> desc_x;
- NdArrayDesc<4> desc_y;
- NdArrayDescsForElementwiseBroadcast(input_condition_shape, input_x_shape, input_y_shape,
- &desc_condition, &desc_x, &desc_y);
-
- // In Tensorflow, the dimensions are canonically named (batch_number, row,
- // col, channel), with extents (batches, height, width, depth), with the
- // trailing dimension changing most rapidly (channels has the smallest
- // stride, typically 1 element).
- //
- // In generated C code, we store arrays with the dimensions reversed. The
- // first dimension has smallest stride.
- //
- // We name our variables by their Tensorflow convention, but generate C code
- // nesting loops such that the innermost loop has the smallest stride for
- // the best cache behavior.
- for (int b = 0; b < extended_output_shape.Dims(0); ++b)
- {
- for (int y = 0; y < extended_output_shape.Dims(1); ++y)
- {
- for (int x = 0; x < extended_output_shape.Dims(2); ++x)
- {
- for (int c = 0; c < extended_output_shape.Dims(3); ++c)
- {
- const int condition_index = SubscriptToIndex(desc_condition, b, y, x, c);
- const int x_index = SubscriptToIndex(desc_x, b, y, x, c);
- const int y_index = SubscriptToIndex(desc_y, b, y, x, c);
- output_data[Offset(extended_output_shape, b, y, x, c)] =
- input_condition_data[condition_index] ? input_x_data[x_index] : input_y_data[y_index];
- }
- }
- }
- }
-}
-
-template <typename D, typename T>
-void SelectTrueCoords(const RuntimeShape &input_condition_shape, const D *input_condition_data,
- T *output_data)
-{
- const size_t size = input_condition_shape.FlatSize();
- if (size == 0)
- {
- // Dimension is zero, in which case we don't need to output.
- return;
- }
- const size_t cond_rank = input_condition_shape.DimensionsCount();
-
- std::vector<int> dims_to_count(cond_rank, 0);
- int cur_flat_size = size;
- for (int i = 0; i < cond_rank; ++i)
- {
- dims_to_count[i] = cur_flat_size / input_condition_shape.Dims(i);
- cur_flat_size = dims_to_count[i];
- }
-
- int output_index = 0;
- for (int i = 0; i < size; ++i)
- {
- if (input_condition_data[i])
- {
- // Insert the coordinate of the current item (row major) into output.
- int flat_index = i;
- for (int j = 0; j < cond_rank; ++j)
- {
- int coord_j = flat_index / dims_to_count[j];
- output_data[output_index * cond_rank + j] = coord_j;
- flat_index %= dims_to_count[j];
- }
- output_index++;
- }
- }
-}
-
-// For easy implementation, the indices is always a vector of size-4 vectors.
-template <typename T, typename TI>
-inline void SparseToDense(const std::vector<std::vector<TI>> &indices, const T *values,
- T default_value, bool value_is_scalar,
- const RuntimeShape &unextended_output_shape, T *output_data)
-{
- TFLITE_DCHECK_LE(unextended_output_shape.DimensionsCount(), 4);
- const RuntimeShape output_shape = RuntimeShape::ExtendedShape(4, unextended_output_shape);
- const int value_count = indices.size();
-
- // First fill the output_data with default value.
- const int num_elements = output_shape.FlatSize();
- for (int i = 0; i < num_elements; ++i)
- {
- output_data[i] = default_value;
- }
-
- // Special handle for value is scalar case to avoid checking the boolean
- // condition within the loop every time.
- if (value_is_scalar)
- {
- for (int i = 0; i < value_count; ++i)
- {
- const std::vector<TI> &index = indices[i];
- TFLITE_DCHECK_EQ(index.size(), 4);
- const T value = *values; // just use the first value.
- output_data[Offset(output_shape, index[0], index[1], index[2], index[3])] = value;
- }
- return;
- }
-
- // Go through the values and indices to fill the sparse values.
- for (int i = 0; i < value_count; ++i)
- {
- const std::vector<TI> &index = indices[i];
- TFLITE_DCHECK_EQ(index.size(), 4);
- const T value = values[i];
- output_data[Offset(output_shape, index[0], index[1], index[2], index[3])] = value;
- }
-}
-
-template <typename T>
-inline void Pow(const RuntimeShape &input1_shape, const T *input1_data,
- const RuntimeShape &input2_shape, const T *input2_data,
- const RuntimeShape &output_shape, T *output_data)
-{
- const int flat_size = MatchingFlatSize(input1_shape, input2_shape, output_shape);
- for (int i = 0; i < flat_size; ++i)
- {
- output_data[i] = std::pow(input1_data[i], input2_data[i]);
- }
-}
-
-template <typename T>
-inline void BroadcastPow4DSlow(const RuntimeShape &unextended_input1_shape, const T *input1_data,
- const RuntimeShape &unextended_input2_shape, const T *input2_data,
- const RuntimeShape &unextended_output_shape, T *output_data)
-{
- TFLITE_DCHECK_LE(unextended_input1_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_input2_shape.DimensionsCount(), 4);
- TFLITE_DCHECK_LE(unextended_output_shape.DimensionsCount(), 4);
- const RuntimeShape output_shape = RuntimeShape::ExtendedShape(4, unextended_output_shape);
-
- NdArrayDesc<4> desc1;
- NdArrayDesc<4> desc2;
- NdArrayDescsForElementwiseBroadcast(unextended_input1_shape, unextended_input2_shape, &desc1,
- &desc2);
-
- for (int b = 0; b < output_shape.Dims(0); ++b)
- {
- for (int y = 0; y < output_shape.Dims(1); ++y)
- {
- for (int x = 0; x < output_shape.Dims(2); ++x)
- {
- for (int c = 0; c < output_shape.Dims(3); ++c)
- {
- auto out_idx = Offset(output_shape, b, y, x, c);
- auto in1_idx = SubscriptToIndex(desc1, b, y, x, c);
- auto in2_idx = SubscriptToIndex(desc2, b, y, x, c);
- auto in1_val = input1_data[in1_idx];
- auto in2_val = input2_data[in2_idx];
- output_data[out_idx] = std::pow(in1_val, in2_val);
- }
- }
- }
- }
-}
-
-template <typename Scalar>
-void Reverse(int axis, const RuntimeShape &input_shape, const Scalar *input_data,
- const RuntimeShape &output_shape, Scalar *output_data)
-{
- ruy::profiler::ScopeLabel label("Reverse");
-
- int outer_size = 1;
- for (int i = 0; i < axis; ++i)
- {
- outer_size *= input_shape.Dims(i);
- }
-
- int copy_size = 1;
- for (int i = axis + 1; i < input_shape.DimensionsCount(); ++i)
- {
- copy_size *= input_shape.Dims(i);
- }
-
- const int dims_at_axis = input_shape.Dims(axis);
- for (int i = 0; i < outer_size; ++i)
- {
- for (int j = 0; j < dims_at_axis; ++j)
- {
- const int start_pos = (i * dims_at_axis + j) * copy_size;
- Scalar *output_ptr = output_data + start_pos;
- int loc = (i * dims_at_axis + dims_at_axis - j - 1) * copy_size;
- memcpy(output_ptr, input_data + loc, copy_size * sizeof(Scalar));
- }
- }
-}
-
-template <typename Scalar, typename TS>
-void ReverseSequence(const TS *seq_lengths, const int seq_dim, const int batch_dim,
- const RuntimeShape &input_shape, const Scalar *input_data,
- const RuntimeShape &output_shape, Scalar *output_data)
-{
- ruy::profiler::ScopeLabel label("ReverseSequence");
-
- int outer_size = 1;
- int outer_dim = std::min(batch_dim, seq_dim);
- int medium_dim = std::max(batch_dim, seq_dim);
- for (int i = 0; i < outer_dim; ++i)
- {
- outer_size *= input_shape.Dims(i);
- }
-
- int medium_size = 1;
- for (int i = outer_dim + 1; i < medium_dim; ++i)
- {
- medium_size *= input_shape.Dims(i);
- }
-
- int copy_size = 1;
- for (int i = medium_dim + 1; i < input_shape.DimensionsCount(); ++i)
- {
- copy_size *= input_shape.Dims(i);
- }
-
- const int dims_at_outer_dim = input_shape.Dims(outer_dim);
- const int dims_at_medium_dim = input_shape.Dims(medium_dim);
-
- Scalar *output_ptr;
- if (batch_dim > seq_dim)
- {
- for (int i = 0; i < outer_size; ++i)
- {
- for (int j = 0; j < dims_at_outer_dim; ++j)
- {
- const int in_pos_base = (i * dims_at_outer_dim + j) * medium_size;
- for (int p = 0; p < medium_size; ++p)
- {
- for (int q = 0; q < dims_at_medium_dim; ++q)
- {
- const int in_pos = ((in_pos_base + p) * dims_at_medium_dim + q) * copy_size;
- const Scalar *in_ptr = input_data + in_pos;
- int sl = seq_lengths[q] - 1;
- if (j > sl)
- {
- output_ptr = output_data + in_pos;
- }
- else
- {
- const int out_pos_base = (i * dims_at_outer_dim + sl - j) * medium_size;
- const int out_pos = ((out_pos_base + p) * dims_at_medium_dim + q) * copy_size;
- output_ptr = output_data + out_pos;
- }
- memcpy(output_ptr, in_ptr, copy_size * sizeof(Scalar));
- }
- }
- }
- }
- }
- else if (batch_dim < seq_dim)
- {
- for (int i = 0; i < outer_size; ++i)
- {
- for (int j = 0; j < dims_at_outer_dim; ++j)
- {
- const int in_pos_base = (i * dims_at_outer_dim + j) * medium_size;
- int sl = seq_lengths[j] - 1;
- const int out_pos_base = (i * dims_at_outer_dim + j) * medium_size;
- for (int p = 0; p < medium_size; ++p)
- {
- for (int q = 0; q < dims_at_medium_dim; ++q)
- {
- const int in_pos = ((in_pos_base + p) * dims_at_medium_dim + q) * copy_size;
- const Scalar *in_ptr = input_data + in_pos;
- if (q > sl)
- {
- output_ptr = output_data + in_pos;
- }
- else
- {
- const int out_pos = ((out_pos_base + p) * dims_at_medium_dim + sl - q) * copy_size;
- output_ptr = output_data + out_pos;
- }
- memcpy(output_ptr, in_ptr, copy_size * sizeof(Scalar));
- }
- }
- }
- }
- }
-}
-
-template <typename T>
-inline void SegmentSum(const RuntimeShape &input_shape, const T *input_data,
- const RuntimeShape &segment_ids_shape, const int32_t *segment_ids_data,
- const RuntimeShape &output_shape, T *output_data)
-{
- const int segment_flat_size = MatchingFlatSizeSkipDim(input_shape, 0, output_shape);
-
- memset(output_data, 0, sizeof(T) * output_shape.FlatSize());
-
- for (int i = 0; i < input_shape.Dims(0); i++)
- {
- int output_index = segment_ids_data[i];
- for (int j = 0; j < segment_flat_size; ++j)
- {
- output_data[output_index * segment_flat_size + j] += input_data[i * segment_flat_size + j];
- }
- }
-}
-
-} // namespace reference_ops
-} // namespace tflite
-
-#endif // LUCI_INTERPRETER_PAL_REFERENCE_OPS_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/pal.cmake b/onert-micro/luci-interpreter/pal/mcu/pal.cmake
index 24e469f0e..fe528ad56 100644
--- a/onert-micro/luci-interpreter/pal/mcu/pal.cmake
+++ b/onert-micro/luci-interpreter/pal/mcu/pal.cmake
@@ -1,56 +1,7 @@
macro(initialize_pal)
- nnas_find_package(TensorFlowSource EXACT 2.8.0 REQUIRED)
- nnas_find_package(TensorFlowGEMMLowpSource EXACT 2.8.0 REQUIRED)
- nnas_find_package(TensorFlowEigenSource EXACT 2.8.0 REQUIRED)
- nnas_find_package(TensorFlowRuySource EXACT 2.8.0 REQUIRED)
-
- if (NOT TensorFlowSource_FOUND)
- message(STATUS "Skipping luci-interpreter: TensorFlow not found")
- return()
- endif ()
-
- if (NOT TensorFlowGEMMLowpSource_FOUND)
- message(STATUS "Skipping luci-interpreter: gemmlowp not found")
- return()
- endif ()
-
- if (NOT TensorFlowEigenSource_FOUND)
- message(STATUS "Skipping luci-interpreter: Eigen not found")
- return()
- endif ()
-
- if (NOT TensorFlowRuySource_FOUND)
- message(STATUS "Skipping luci-interpreter: Ruy not found")
- return()
- endif ()
- #find_package(Threads REQUIRED)
-
set(PAL_INITIALIZED TRUE)
endmacro()
macro(add_pal_to_target TGT)
- target_include_directories(${TGT} PRIVATE "${PAL}")
- target_include_directories(${TGT} PRIVATE
- "${TensorFlowRuySource_DIR}"
- "${TensorFlowGEMMLowpSource_DIR}"
- "${TensorFlowEigenSource_DIR}"
- "${TensorFlowSource_DIR}")
- target_include_directories(${TGT} PRIVATE ${LUCI_INTERPRETER_PAL_DIR})
-
- # TODO put it back, I changed my mind.
- # instead add sources with visitors in this library
- set(PAL_SOURCES ${TensorFlowSource_DIR}/tensorflow/lite/kernels/internal/quantization_util.cc
- ${TensorFlowSource_DIR}/tensorflow/lite/kernels/internal/tensor_utils.cc
- ${TensorFlowSource_DIR}/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.cc)
- add_library(luci_interpreter_mcu_pal STATIC ${PAL_SOURCES})
- set_target_properties(luci_interpreter_mcu_pal PROPERTIES POSITION_INDEPENDENT_CODE ON)
- target_include_directories(luci_interpreter_mcu_pal PRIVATE
- "${TensorFlowRuySource_DIR}"
- "${TensorFlowGEMMLowpSource_DIR}"
- "${TensorFlowEigenSource_DIR}"
- "${TensorFlowSource_DIR}"
- )
-
- target_link_libraries(${TGT} PRIVATE luci_interpreter_mcu_pal)
- #target_link_libraries(${TGT} PRIVATE Threads::Threads luci_interpreter_mcu_pal)
+ target_include_directories(${TGT} PUBLIC ${LUCI_INTERPRETER_PAL_DIR})
endmacro()
diff --git a/onert-micro/luci-interpreter/src/Interpreter.cpp b/onert-micro/luci-interpreter/src/Interpreter.cpp
index dccef8220..658b28ff7 100644
--- a/onert-micro/luci-interpreter/src/Interpreter.cpp
+++ b/onert-micro/luci-interpreter/src/Interpreter.cpp
@@ -52,9 +52,9 @@ Interpreter::Interpreter(const char *model_data_raw, const InterpreterConfigure
#else
// Construct default interpreter with dynamic allocations and with input allocations
-Interpreter::Interpreter(const char *model_data_raw)
+Interpreter::Interpreter(const char *model_data_raw, bool dealloc_input)
{
- ModuleLoader::load(&_runtime_module, &_memory_manager, model_data_raw);
+ ModuleLoader::load(&_runtime_module, &_memory_manager, model_data_raw, dealloc_input);
}
#endif // USE_STATIC_ALLOC
diff --git a/onert-micro/luci-interpreter/src/core/RuntimeGraph.cpp b/onert-micro/luci-interpreter/src/core/RuntimeGraph.cpp
index 41447f9d7..917ebbbbf 100644
--- a/onert-micro/luci-interpreter/src/core/RuntimeGraph.cpp
+++ b/onert-micro/luci-interpreter/src/core/RuntimeGraph.cpp
@@ -24,10 +24,13 @@ namespace luci_interpreter
{
// IBaseRuntimeGraph
-RuntimeGraph::RuntimeGraph(SimpleMemoryManager *memory_manager, CircleReader *circle_reader)
+RuntimeGraph::RuntimeGraph(SimpleMemoryManager *memory_manager, CircleReader *circle_reader,
+ RuntimeModule *runtime_module, uint32_t subgraph_index)
: _memory_manager(memory_manager),
_tensor_to_data(std::unordered_map<const circle::Tensor *, uint8_t *>{}),
- _reader(circle_reader), _inplace_op_indexes(std::unordered_set<uint32_t>{})
+ _runtime_module(runtime_module), _reader(circle_reader),
+ _inplace_op_indexes(std::unordered_set<const circle::Operator *>{}),
+ _subgraph_index(subgraph_index)
{
}
@@ -42,19 +45,23 @@ RuntimeGraph::~RuntimeGraph()
}
// TODO: modify this
-void RuntimeGraph::buildAllocDeallocPlan()
+void RuntimeGraph::buildAllocDeallocPlan(bool dealloc_input)
{
+ assert(_reader->get_current_subgraph_index() == _subgraph_index);
invalidate();
using Lifetime = std::pair<int32_t, int32_t>;
std::map<const circle::Tensor *, Lifetime> lifetimes;
const size_t num_kernels = _reader->operators().size();
- for (const auto input_ind : _reader->inputs())
+ if (dealloc_input)
{
- const auto raw_tensor = _reader->tensors()[input_ind];
+ for (const auto input_ind : _reader->inputs())
+ {
+ const auto raw_tensor = _reader->tensors()[input_ind];
- assert(lifetimes.count(raw_tensor) == 0);
- lifetimes[raw_tensor] = Lifetime(-1, 0);
+ assert(lifetimes.count(raw_tensor) == 0);
+ lifetimes[raw_tensor] = Lifetime(-1, 0);
+ }
}
for (int32_t index = 0; index < num_kernels; ++index)
@@ -72,16 +79,12 @@ void RuntimeGraph::buildAllocDeallocPlan()
const auto raw_tensor = _reader->tensors()[input_index];
// Pass constant tensors
- auto const &buffer = wrap(_reader->buffers()[raw_tensor->buffer()]->data());
- if (not buffer.empty())
- {
- // unknown shape tensor and scalar tensor
+ if (Tensor::is_constant_tensor(_reader, raw_tensor))
continue;
- }
if (lifetimes.count(raw_tensor) > 0)
{
- if (_inplace_op_indexes.find(index) != _inplace_op_indexes.end())
+ if (_inplace_op_indexes.find(kernel) != _inplace_op_indexes.end())
lifetimes.at(raw_tensor).second = -1;
else
lifetimes.at(raw_tensor).second = index;
@@ -94,7 +97,7 @@ void RuntimeGraph::buildAllocDeallocPlan()
const auto raw_tensor = _reader->tensors()[output_index];
assert(lifetimes.count(raw_tensor) == 0);
- if (_inplace_op_indexes.find(index) != _inplace_op_indexes.end())
+ if (_inplace_op_indexes.find(kernel) != _inplace_op_indexes.end())
lifetimes[raw_tensor] = Lifetime(-1, index);
else
lifetimes[raw_tensor] = Lifetime(index, index);
@@ -123,6 +126,7 @@ void RuntimeGraph::buildAllocDeallocPlan()
void RuntimeGraph::allocate(size_t kernel_index)
{
+ assert(_reader->get_current_subgraph_index() == _subgraph_index);
assert(_is_valid && kernel_index < _alloc_plan.size());
for (const circle::Tensor *tensor : _alloc_plan[kernel_index])
{
@@ -136,8 +140,37 @@ void RuntimeGraph::allocate(size_t kernel_index)
}
}
+#ifndef DIS_DYN_SHAPES
+void RuntimeGraph::addDynamicShapeTensor(const circle::Tensor *tensor,
+ luci_interpreter::RuntimeShape &&shapes)
+{
+ assert(_reader->get_current_subgraph_index() == _subgraph_index);
+ _dynamic_tensor_shapes[tensor] = std::move(shapes);
+}
+
+luci_interpreter::RuntimeShape *RuntimeGraph::getDynamicShapeTensor(const circle::Tensor *tensor)
+{
+ assert(_reader->get_current_subgraph_index() == _subgraph_index);
+ auto it = _dynamic_tensor_shapes.find(tensor);
+
+ return it == _dynamic_tensor_shapes.end() ? nullptr : &_dynamic_tensor_shapes[tensor];
+}
+
+void RuntimeGraph::removeDynamicShapeTensor(const circle::Tensor *tensor)
+{
+ assert(_reader->get_current_subgraph_index() == _subgraph_index);
+ auto it = _dynamic_tensor_shapes.find(tensor);
+
+ assert(it != _dynamic_tensor_shapes.end());
+
+ _dynamic_tensor_shapes.erase(it);
+}
+
+#endif // DIS_DYN_SHAPES
+
void RuntimeGraph::deallocate(size_t kernel_index)
{
+ assert(_reader->get_current_subgraph_index() == _subgraph_index);
assert(_is_valid && kernel_index < _dealloc_plan.size());
for (const circle::Tensor *tensor : _dealloc_plan[kernel_index])
{
@@ -151,12 +184,31 @@ void RuntimeGraph::deallocate(size_t kernel_index)
}
}
+void RuntimeGraph::resetTensorData(uint8_t *new_data, const circle::Tensor *tensor)
+{
+ assert(_reader->get_current_subgraph_index() == _subgraph_index);
+ auto tensor_it = _tensor_to_data.find(tensor);
+ if (tensor_it != _tensor_to_data.end())
+ {
+ auto *data = _tensor_to_data.at(tensor);
+ _memory_manager->release_memory(data);
+ }
+
+ _tensor_to_data[tensor] = new_data;
+}
+
void RuntimeGraph::resetOutputTensorsData()
{
+ assert(_reader->get_current_subgraph_index() == _subgraph_index);
+ const auto graph_inputs = _reader->inputs();
for (int i = 0; i < _reader->outputs().size(); ++i)
{
const auto tensor_index = _reader->outputs()[i];
assert(tensor_index != -1);
+
+ if (std::find(graph_inputs.begin(), graph_inputs.end(), tensor_index) != graph_inputs.end())
+ return;
+
const auto tensor = _reader->tensors()[tensor_index];
assert(tensor != nullptr);
@@ -172,29 +224,22 @@ void RuntimeGraph::resetOutputTensorsData()
uint8_t *RuntimeGraph::configureGraphInput(int32_t input_index)
{
- resetOutputTensorsData();
+ assert(_reader->get_current_subgraph_index() == _subgraph_index);
const auto tensor_index = _reader->inputs()[input_index];
assert(tensor_index != -1);
const auto tensor = _reader->tensors()[tensor_index];
assert(tensor != nullptr);
- if (_tensor_to_data.find(tensor) != _tensor_to_data.end())
- {
- auto *data = _tensor_to_data.at(tensor);
- _memory_manager->release_memory(data);
- }
-
auto *data = _memory_manager->allocate_memory(tensor);
- _tensor_to_data[tensor] = data;
+ configureGraphInput(input_index, data);
return data;
}
-// To save data
-// TODO maybe remove it
void RuntimeGraph::configureGraphInput(int32_t input_index, uint8_t *data)
{
+ assert(_reader->get_current_subgraph_index() == _subgraph_index);
resetOutputTensorsData();
const auto tensor_index = _reader->inputs()[input_index];
@@ -205,13 +250,15 @@ void RuntimeGraph::configureGraphInput(int32_t input_index, uint8_t *data)
if (_tensor_to_data.find(tensor) != _tensor_to_data.end())
{
auto *data_prev = _tensor_to_data.at(tensor);
- _memory_manager->release_memory(data_prev);
+ if (data_prev != data)
+ _memory_manager->release_memory(data_prev);
}
_tensor_to_data[tensor] = data;
}
int32_t RuntimeGraph::getInputDataSizeByIndex(int32_t input_index)
{
+ assert(_reader->get_current_subgraph_index() == _subgraph_index);
const auto tensor_index = _reader->inputs()[input_index];
assert(tensor_index != -1);
const auto tensor = _reader->tensors()[tensor_index];
@@ -220,8 +267,42 @@ int32_t RuntimeGraph::getInputDataSizeByIndex(int32_t input_index)
return Tensor::num_elements(tensor) * size(Tensor::element_type(tensor));
}
+int32_t RuntimeGraph::getNumOfInputTensors()
+{
+ assert(_reader->get_current_subgraph_index() == _subgraph_index);
+ return _reader->inputs().size();
+}
+
+int32_t RuntimeGraph::getNumOfOutputTensors()
+{
+ assert(_reader->get_current_subgraph_index() == _subgraph_index);
+ return _reader->outputs().size();
+}
+
+const circle::Tensor *RuntimeGraph::getInputTensorByIndex(int32_t input_index)
+{
+ assert(_reader->get_current_subgraph_index() == _subgraph_index);
+
+ const auto tensor_index = _reader->inputs()[input_index];
+ const auto tensor = _reader->tensors()[tensor_index];
+ assert(tensor != nullptr);
+ return tensor;
+}
+
+const circle::Tensor *RuntimeGraph::getOutputTensorByIndex(int32_t input_index)
+{
+ assert(_reader->get_current_subgraph_index() == _subgraph_index);
+
+ const auto tensor_index = _reader->outputs()[input_index];
+ const auto tensor = _reader->tensors()[tensor_index];
+ assert(tensor != nullptr);
+ return tensor;
+}
+
int32_t RuntimeGraph::getOutputDataSizeByIndex(int32_t output_index)
{
+ assert(_reader->get_current_subgraph_index() == _subgraph_index);
+
const auto tensor_index = _reader->outputs()[output_index];
assert(tensor_index != -1);
const auto tensor = _reader->tensors()[tensor_index];
@@ -232,6 +313,8 @@ int32_t RuntimeGraph::getOutputDataSizeByIndex(int32_t output_index)
uint8_t *RuntimeGraph::getOutputDataByIndex(int32_t output_index)
{
+ assert(_reader->get_current_subgraph_index() == _subgraph_index);
+
const auto tensor_index = _reader->outputs()[output_index];
assert(tensor_index != -1);
const auto tensor = _reader->tensors()[tensor_index];
@@ -244,6 +327,8 @@ uint8_t *RuntimeGraph::getOutputDataByIndex(int32_t output_index)
uint8_t *RuntimeGraph::getDataByTensor(const circle::Tensor *raw_tensor)
{
+ assert(_reader->get_current_subgraph_index() == _subgraph_index);
+
if (raw_tensor == nullptr)
return nullptr;
@@ -255,20 +340,29 @@ uint8_t *RuntimeGraph::getDataByTensor(const circle::Tensor *raw_tensor)
return _tensor_to_data.at(raw_tensor);
}
-void RuntimeGraph::makeInplaceOperation(const circle::Tensor *src_tensor,
+void RuntimeGraph::clearTensors() { _tensor_to_data.clear(); }
+
+void RuntimeGraph::makeInplaceOperation(const circle::Tensor *removing_tensor,
const circle::Tensor *dst_tensor)
{
- if (src_tensor == nullptr or dst_tensor == nullptr)
- return;
+ assert(_reader->get_current_subgraph_index() == _subgraph_index);
+ assert(removing_tensor != nullptr);
- auto src_it = _tensor_to_data.find(src_tensor);
+ auto src_it = _tensor_to_data.find(removing_tensor);
- assert(src_it != _tensor_to_data.end() && "Failed makeInplaceOperation");
+ if (src_it == _tensor_to_data.end())
+ return;
- auto *data = _tensor_to_data[src_tensor];
+ auto *data = _tensor_to_data[removing_tensor];
_tensor_to_data.erase(src_it);
+ if (dst_tensor == nullptr)
+ {
+ delete[] data;
+ return;
+ }
+
assert(_tensor_to_data.find(dst_tensor) == _tensor_to_data.end() &&
"Failed makeInplaceOperation");
_tensor_to_data[dst_tensor] = data;
@@ -276,6 +370,7 @@ void RuntimeGraph::makeInplaceOperation(const circle::Tensor *src_tensor,
uint8_t *RuntimeGraph::getConstDataByTensor(const circle::Tensor *raw_tensor)
{
+ assert(_reader->get_current_subgraph_index() == _subgraph_index);
if (raw_tensor == nullptr)
return nullptr;
@@ -286,6 +381,7 @@ uint8_t *RuntimeGraph::getConstDataByTensor(const circle::Tensor *raw_tensor)
const circle::Tensor *RuntimeGraph::getCircleTensorByIndex(int32_t index)
{
+ assert(_reader->get_current_subgraph_index() == _subgraph_index);
if (index < 0)
return nullptr;
@@ -294,9 +390,9 @@ const circle::Tensor *RuntimeGraph::getCircleTensorByIndex(int32_t index)
return raw_tensor;
}
-void RuntimeGraph::configure()
+void RuntimeGraph::configure(bool dealloc_input)
{
- KernelConfigureRegistry kernel_configure;
+ selectOwnSubgraph();
for (uint32_t i = 0; i < _reader->operators().size(); ++i)
{
@@ -309,33 +405,36 @@ void RuntimeGraph::configure()
}
if (not _is_valid)
- buildAllocDeallocPlan();
+ buildAllocDeallocPlan(dealloc_input);
_is_valid = true;
}
+void RuntimeGraph::setDataToTensor(const circle::Tensor *tensor, uint8_t *data)
+{
+ _tensor_to_data[tensor] = data;
+}
+
void RuntimeGraph::execute()
{
+ selectOwnSubgraph();
+
if (not _is_valid)
- configure();
+ configure(true);
- KernelExecuteRegistry kernel_executor;
+ const auto operators_size = _reader->operators().size();
+ const auto operators = _reader->operators();
- for (uint32_t i = 0; i < _reader->operators().size(); ++i)
+ for (uint32_t i = 0; i < operators_size; ++i)
{
- const auto op = _reader->operators().at(i);
+ const auto op = operators.at(i);
assert(op != nullptr);
const auto opcode = _reader->builtin_code(op);
allocate(i);
- bool is_inplace = false;
-
- if (_inplace_op_indexes.find(i) != _inplace_op_indexes.end())
- is_inplace = true;
-
- kernel_executor.execute_kernel(op, opcode, this, is_inplace);
+ kernel_executor.execute_kernel(op, opcode, this);
deallocate(i);
}
diff --git a/onert-micro/luci-interpreter/src/core/RuntimeGraph.h b/onert-micro/luci-interpreter/src/core/RuntimeGraph.h
index b64e8dc78..baac0b1b9 100644
--- a/onert-micro/luci-interpreter/src/core/RuntimeGraph.h
+++ b/onert-micro/luci-interpreter/src/core/RuntimeGraph.h
@@ -57,7 +57,10 @@ public:
class RuntimeGraph
{
public:
- explicit RuntimeGraph(SimpleMemoryManager *memory_manager, CircleReader *circle_reader);
+ RuntimeGraph() = delete;
+
+ explicit RuntimeGraph(SimpleMemoryManager *memory_manager, CircleReader *circle_reader,
+ RuntimeModule *runtime_module, uint32_t subgraph_index);
~RuntimeGraph();
Tensor *addTensor(const circle::Tensor *raw_tensor, std::unique_ptr<Tensor> &&tensor);
@@ -75,35 +78,70 @@ public:
int32_t getInputDataSizeByIndex(int32_t input_index);
int32_t getOutputDataSizeByIndex(int32_t output_index);
+ int32_t getNumOfInputTensors();
+ int32_t getNumOfOutputTensors();
+
+ const circle::Tensor *getInputTensorByIndex(int32_t input_index);
+ const circle::Tensor *getOutputTensorByIndex(int32_t input_index);
+
uint8_t *getOutputDataByIndex(int32_t output_index);
- void addInplaceOpIndex(uint32_t index) { _inplace_op_indexes.insert(index); }
+ void addInplaceOpIndex(const circle::Operator *op) { _inplace_op_indexes.insert(op); }
void execute();
- void configure();
+ void configure(bool dealloc_input);
void invalidate() { _is_valid = false; }
bool isValid() const { return _is_valid; }
+ void selectOwnSubgraph() { _reader->select_subgraph(_subgraph_index); };
+ void resetOutputTensorsData();
+
+ void clearTensors();
+
+ void setDataToTensor(const circle::Tensor *tensor, uint8_t *data);
+
+ void resetTensorData(uint8_t *new_data, const circle::Tensor *tensor);
+
+ RuntimeModule *getRuntimeModule() { return _runtime_module; };
+
+ bool is_inplace_op(const circle::Operator *op)
+ {
+ return _inplace_op_indexes.find(op) != _inplace_op_indexes.end();
+ }
+
+#ifndef DIS_DYN_SHAPES
+ void addDynamicShapeTensor(const circle::Tensor *tensor, luci_interpreter::RuntimeShape &&shapes);
+
+ luci_interpreter::RuntimeShape *getDynamicShapeTensor(const circle::Tensor *tensor);
+
+ void removeDynamicShapeTensor(const circle::Tensor *tensor);
+#endif // DIS_DYN_SHAPES
+
private:
- void buildAllocDeallocPlan();
+ void buildAllocDeallocPlan(bool dealloc_input);
void allocate(size_t kernel_index);
void deallocate(size_t kernel_index);
- void resetOutputTensorsData();
-
private:
SimpleMemoryManager *_memory_manager;
CircleReader *_reader;
+ RuntimeModule *_runtime_module;
std::unordered_map<const circle::Tensor *, uint8_t *> _tensor_to_data;
- std::unordered_set<uint32_t> _inplace_op_indexes;
+ std::unordered_set<const circle::Operator *> _inplace_op_indexes;
bool _is_valid = false;
// Tensors that are not used anymore after given op
std::vector<std::vector<const circle::Tensor *>> _alloc_plan;
std::vector<std::vector<const circle::Tensor *>> _dealloc_plan;
+
+ uint32_t _subgraph_index;
+
+#ifndef DIS_DYN_SHAPES
+ std::unordered_map<const circle::Tensor *, luci_interpreter::RuntimeShape> _dynamic_tensor_shapes;
+#endif // DIS_DYN_SHAPES
};
#endif // USE_STATIC_ALLOC
diff --git a/onert-micro/luci-interpreter/src/core/RuntimeModule.h b/onert-micro/luci-interpreter/src/core/RuntimeModule.h
index 5dbe5a967..d42698277 100644
--- a/onert-micro/luci-interpreter/src/core/RuntimeModule.h
+++ b/onert-micro/luci-interpreter/src/core/RuntimeModule.h
@@ -41,7 +41,8 @@ public:
void addGraph(MemoryManager *memory_manager)
{
- _graphs.emplace_back(memory_manager, &_circle_reader);
+ _graphs.emplace_back(memory_manager, &_circle_reader, this,
+ _circle_reader.get_current_subgraph_index());
}
BaseRuntimeGraph *getRuntimeGraphAt(uint32_t pos) { return &_graphs.at(pos); }
@@ -52,6 +53,8 @@ public:
BaseRuntimeGraph *getMainGraph() const { return const_cast<BaseRuntimeGraph *>(&_graphs[0]); }
+ void selectSubgraph(uint32_t index) { _circle_reader.select_subgraph(index); }
+
private:
std::vector<BaseRuntimeGraph> _graphs;
diff --git a/onert-micro/luci-interpreter/src/core/reader/CircleMicroReader.cpp b/onert-micro/luci-interpreter/src/core/reader/CircleMicroReader.cpp
index 332e464bd..06d93f27f 100644
--- a/onert-micro/luci-interpreter/src/core/reader/CircleMicroReader.cpp
+++ b/onert-micro/luci-interpreter/src/core/reader/CircleMicroReader.cpp
@@ -139,6 +139,8 @@ bool CircleReader::select_subgraph(uint32_t sgindex)
_current_subgraph = subgraphs->Get(sgindex);
assert(_current_subgraph != nullptr);
+ _current_subgraph_index = sgindex;
+
return true;
}
diff --git a/onert-micro/luci-interpreter/src/kernels/Abs.cpp b/onert-micro/luci-interpreter/src/kernels/Abs.cpp
new file mode 100644
index 000000000..98acd13e2
--- /dev/null
+++ b/onert-micro/luci-interpreter/src/kernels/Abs.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Builders.h"
+#include "kernels/Utils.h"
+#include "PALAbs.h"
+
+namespace luci_interpreter
+{
+
+void configure_kernel_CircleAbs(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+ const auto input_index = cur_op->inputs()->operator[](0);
+ const auto output_index = cur_op->outputs()->operator[](0);
+
+ assert(input_index != -1);
+ assert(output_index != -1);
+
+ const auto input = runtime_graph->getCircleTensorByIndex(input_index);
+ auto output = runtime_graph->getCircleTensorByIndex(output_index);
+
+ assert(input != nullptr);
+ assert(output != nullptr);
+
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(input) == Tensor::element_type(output));
+ LUCI_INTERPRETER_CHECK(Tensor::num_dims(input) == Tensor::num_dims(output));
+ LUCI_INTERPRETER_CHECK(Tensor::num_elements(input) == Tensor::num_elements(output));
+}
+
+void execute_kernel_CircleAbs(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+ const auto input_index = cur_op->inputs()->operator[](0);
+ const auto output_index = cur_op->outputs()->operator[](0);
+
+ assert(input_index != -1);
+ assert(output_index != -1);
+
+ const auto input = runtime_graph->getCircleTensorByIndex(input_index);
+ auto output = runtime_graph->getCircleTensorByIndex(output_index);
+
+ assert(input != nullptr);
+ assert(output != nullptr);
+
+ bool is_inplace = runtime_graph->is_inplace_op(cur_op);
+
+ const uint8_t *input_data = runtime_graph->getDataByTensor(input);
+ uint8_t *output_data = runtime_graph->getDataByTensor(output);
+
+ if (is_inplace)
+ {
+ output_data = const_cast<uint8_t *>(input_data);
+ }
+
+ assert(input_data != nullptr);
+ assert(output_data != nullptr);
+
+ const int flat_size = kernels::getTensorRuntimeShape(input, runtime_graph).flatSize();
+
+ switch (Tensor::element_type(input))
+ {
+#ifndef DIS_FLOAT
+ case DataType::FLOAT32:
+ luci_interpreter_pal::Abs(flat_size, kernels::getTensorData<float>(input_data),
+ kernels::getTensorData<float>(output_data));
+ break;
+#endif // DIS_FLOAT
+ default:
+ assert(false && "Unsupported type.");
+ }
+
+ if (is_inplace)
+ {
+ runtime_graph->makeInplaceOperation(input, output);
+ }
+}
+
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Abs.test.cpp b/onert-micro/luci-interpreter/src/kernels/Abs.test.cpp
new file mode 100644
index 000000000..1e44e2f6c
--- /dev/null
+++ b/onert-micro/luci-interpreter/src/kernels/Abs.test.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/TestUtils.h"
+#include "luci_interpreter/test_models/abs/FloatAbsKernel.h"
+#include "luci_interpreter/test_models/abs/NegAbsKernel.h"
+
+#include "loader/ModuleLoader.h"
+
+namespace luci_interpreter
+{
+namespace
+{
+
+using namespace testing;
+
+class AbsTest : public ::testing::Test
+{
+ // Do nothing
+};
+
+template <typename T> std::vector<T> checkAbsKernel(test_kernel::TestDataBase<T> *test_data_base)
+{
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
+
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
+
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
+
+ runtime_module.execute();
+
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
+
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
+}
+
+TEST_F(AbsTest, Float_P)
+{
+ test_kernel::TestDataFloatAbs test_data_kernel;
+ std::vector<float> output_data_vector = checkAbsKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(AbsTest, Input_output_type_mismatch_NEG)
+{
+ test_kernel::NegTestDataInputOutputTypeMismatchAbsKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
+}
+
+TEST_F(AbsTest, Input_output_shape_mismatch_NEG)
+{
+ test_kernel::NegTestDataInputOutputShapeMismatchAbsKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
+}
+
+} // namespace
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Add.cpp b/onert-micro/luci-interpreter/src/kernels/Add.cpp
index 07b6c200e..6e0398cc7 100644
--- a/onert-micro/luci-interpreter/src/kernels/Add.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Add.cpp
@@ -15,205 +15,108 @@
* limitations under the License.
*/
-#include "kernels/Add.h"
+#include "Builders.h"
+#include "kernels/Utils.h"
#include "kernels/BinaryOpCommon.h"
-#include "kernels/Utils.h"
-#include <tensorflow/lite/kernels/internal/reference/add.h>
-#include <tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h>
+#include "PALAdd.h"
namespace luci_interpreter
{
-namespace kernels
-{
-
-Add::Add(const Tensor *input1, const Tensor *input2, Tensor *output, const AddParams &params)
- : KernelWithParams<AddParams>({input1, input2}, {output}, params)
-{
-}
-
-void Add::configure()
-{
- LUCI_INTERPRETER_CHECK(input1()->element_type() == input2()->element_type());
- LUCI_INTERPRETER_CHECK(input1()->element_type() == output()->element_type());
- if (input1()->element_type() == DataType::S16)
- {
- LUCI_INTERPRETER_CHECK(input1()->zero_points().size() == 1 &&
- input2()->zero_points().size() == 1);
- LUCI_INTERPRETER_CHECK(input1()->zero_point() == 0 && input2()->zero_point() == 0 &&
- output()->zero_point() == 0);
- }
-
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(calculateShapeForBroadcast(input1()->shape(), input2()->shape()));
-}
-
-void Add::execute() const
-{
- switch (input1()->element_type())
- {
- case DataType::FLOAT32:
- evalFloat();
- break;
- case DataType::S64:
- evalInteger<int64_t>();
- break;
- case DataType::S32:
- evalInteger<int32_t>();
- break;
- case DataType::U8:
- evalQuantized();
- break;
- case DataType::S16:
- evalQuantizedS16();
- break;
- default:
- assert(false && "Unsupported type.");
- }
-}
-
-void Add::evalFloat() const
-{
- tflite::ArithmeticParams params{};
- fillArithmeticActivationRange<float>(params, _params.activation);
-
- const bool need_broadcast = tflite::reference_ops::ProcessBroadcastShapes(
- getTensorShape(input1()), getTensorShape(input2()), &params);
- if (need_broadcast)
- {
- tflite::reference_ops::BroadcastAdd4DSlow(
- params, getTensorShape(input1()), getTensorData<float>(input1()), getTensorShape(input2()),
- getTensorData<float>(input2()), getTensorShape(output()), getTensorData<float>(output()));
- }
- else
- {
- tflite::reference_ops::Add(params, getTensorShape(input1()), getTensorData<float>(input1()),
- getTensorShape(input2()), getTensorData<float>(input2()),
- getTensorShape(output()), getTensorData<float>(output()));
- }
-}
-
-template <typename T> void Add::evalInteger() const
+void configure_kernel_CircleAdd(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- tflite::ArithmeticParams params{};
- fillArithmeticActivationRange<T>(params, _params.activation);
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
- const bool need_broadcast = tflite::reference_ops::ProcessBroadcastShapes(
- getTensorShape(input1()), getTensorShape(input2()), &params);
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+ Tensor::element_type(kernel.input2()));
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+ Tensor::element_type(kernel.input2()));
- if (need_broadcast)
+#ifndef DIS_QUANT
+ if (Tensor::element_type(kernel.input1()) == DataType::S16)
{
- tflite::reference_ops::BroadcastAdd4DSlow(
- params, getTensorShape(input1()), getTensorData<T>(input1()), getTensorShape(input2()),
- getTensorData<T>(input2()), getTensorShape(output()), getTensorData<T>(output()));
- }
- else
- {
- tflite::reference_ops::Add(params, getTensorShape(input1()), getTensorData<T>(input1()),
- getTensorShape(input2()), getTensorData<T>(input2()),
- getTensorShape(output()), getTensorData<T>(output()));
+ LUCI_INTERPRETER_CHECK(Tensor::zero_points(kernel.input1()).size() == 1 &&
+ Tensor::zero_points(kernel.input2()).size() == 1);
+ LUCI_INTERPRETER_CHECK(Tensor::zero_point(kernel.input1()) == 0 &&
+ Tensor::zero_point(kernel.input2()) == 0 &&
+ Tensor::zero_point(kernel.output()) == 0);
}
+#endif // DIS_QUANT
}
-void Add::evalQuantized() const
+void execute_kernel_CircleAdd(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- const auto input1_scale = static_cast<double>(input1()->scale());
- const auto input2_scale = static_cast<double>(input2()->scale());
- const auto output_scale = static_cast<double>(output()->scale());
-
- const int left_shift = 20;
- const double twice_max_input_scale = 2 * std::max(input1_scale, input2_scale);
- const double real_input1_multiplier = input1_scale / twice_max_input_scale;
- const double real_input2_multiplier = input2_scale / twice_max_input_scale;
- const double real_output_multiplier = twice_max_input_scale / ((1 << left_shift) * output_scale);
-
- int32_t input1_multiplier{}, input2_multiplier{}, output_multiplier{};
- int input1_shift{}, input2_shift{}, output_shift{};
- quantizeMultiplierSmallerThanOneExp(real_input1_multiplier, &input1_multiplier, &input1_shift);
- quantizeMultiplierSmallerThanOneExp(real_input2_multiplier, &input2_multiplier, &input2_shift);
- quantizeMultiplierSmallerThanOneExp(real_output_multiplier, &output_multiplier, &output_shift);
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
- int32_t activation_min{};
- int32_t activation_max{};
- calculateActivationRangeQuantized(_params.activation, output(), &activation_min, &activation_max);
+ const auto *options = cur_op->builtin_options_as_AddOptions();
- tflite::ArithmeticParams params{};
- params.left_shift = left_shift;
- // The kernel expects inputs' zero points to be negated.
- params.input1_offset = -input1()->zero_point(); // Note the '-'.
- params.input1_multiplier = input1_multiplier;
- params.input1_shift = input1_shift;
- params.input2_offset = -input2()->zero_point(); // Note the '-'.
- params.input2_multiplier = input2_multiplier;
- params.input2_shift = input2_shift;
- params.output_offset = output()->zero_point();
- params.output_multiplier = output_multiplier;
- params.output_shift = output_shift;
- params.quantized_activation_min = activation_min;
- params.quantized_activation_max = activation_max;
+ luci_interpreter::RuntimeShape input_shape1 =
+ kernels::getTensorRuntimeShape(kernel.input1(), runtime_graph);
+ luci_interpreter::RuntimeShape input_shape2 =
+ kernels::getTensorRuntimeShape(kernel.input2(), runtime_graph);
- const bool need_broadcast = tflite::reference_ops::ProcessBroadcastShapes(
- getTensorShape(input1()), getTensorShape(input2()), &params);
+ bool is_inplace = runtime_graph->is_inplace_op(cur_op);
- if (need_broadcast)
+ switch (Tensor::element_type(kernel.input1()))
{
- tflite::reference_ops::BroadcastAdd4DSlow(
- params, getTensorShape(input1()), getTensorData<uint8_t>(input1()), getTensorShape(input2()),
- getTensorData<uint8_t>(input2()), getTensorShape(output()), getTensorData<uint8_t>(output()));
- }
- else
- {
- tflite::reference_ops::Add(params, getTensorShape(input1()), getTensorData<uint8_t>(input1()),
- getTensorShape(input2()), getTensorData<uint8_t>(input2()),
- getTensorShape(output()), getTensorData<uint8_t>(output()));
+#ifndef DIS_FLOAT
+ case DataType::FLOAT32:
+ {
+ auto tiso_func = luci_interpreter_pal::Add<float>;
+ auto broadcast_tiso_func = luci_interpreter_pal::BroadcastAdd4DSlow<float>;
+ if (is_inplace)
+ {
+ kernels::evalTISOInplaceKernel<float>(tiso_func, broadcast_tiso_func, &kernel, options,
+ std::move(input_shape1), std::move(input_shape2));
+ }
+ else
+ {
+ kernels::TISOData kernel_data = kernel.readData();
+ kernels::evalTISOKernel<float>(tiso_func, broadcast_tiso_func, &kernel, &kernel_data,
+ options, std::move(input_shape1), std::move(input_shape2));
+ }
+ }
+ break;
+#endif // DIS_FLOAT
+ case DataType::S64:
+ {
+ auto tiso_func = luci_interpreter_pal::Add<int64_t>;
+ auto broadcast_tiso_func = luci_interpreter_pal::BroadcastAdd4DSlow<int64_t>;
+ if (is_inplace)
+ {
+ kernels::evalTISOInplaceKernel<int64_t>(tiso_func, broadcast_tiso_func, &kernel, options,
+ std::move(input_shape1), std::move(input_shape2));
+ }
+ else
+ {
+ kernels::TISOData kernel_data = kernel.readData();
+ kernels::evalTISOKernel<int64_t>(tiso_func, broadcast_tiso_func, &kernel, &kernel_data,
+ options, std::move(input_shape1), std::move(input_shape2));
+ }
+ }
+ break;
+ case DataType::S32:
+ {
+ auto tiso_func = luci_interpreter_pal::Add<int32_t>;
+ auto broadcast_tiso_func = luci_interpreter_pal::BroadcastAdd4DSlow<int32_t>;
+ if (is_inplace)
+ {
+ kernels::evalTISOInplaceKernel<int32_t>(tiso_func, broadcast_tiso_func, &kernel, options,
+ std::move(input_shape1), std::move(input_shape2));
+ }
+ else
+ {
+ kernels::TISOData kernel_data = kernel.readData();
+ kernels::evalTISOKernel<int32_t>(tiso_func, broadcast_tiso_func, &kernel, &kernel_data,
+ options, std::move(input_shape1), std::move(input_shape2));
+ }
+ }
+ break;
+ default:
+ assert(false && "Unsupported type.");
}
}
-void Add::evalQuantizedS16() const
-{
- const auto input1_scale = static_cast<double>(input1()->scale());
- const auto input2_scale = static_cast<double>(input2()->scale());
- const auto output_scale = static_cast<double>(output()->scale());
-
- constexpr int left_shift = 12;
- const double twice_max_input_scale = 2 * std::max(input1_scale, input2_scale);
- const double real_input1_multiplier = input1_scale / twice_max_input_scale;
- const double real_input2_multiplier = input2_scale / twice_max_input_scale;
- const double real_output_multiplier = twice_max_input_scale / ((1 << left_shift) * output_scale);
-
- int32_t input1_multiplier{}, input2_multiplier{}, output_multiplier{};
- int input1_shift{}, input2_shift{}, output_shift{};
- quantizeMultiplierSmallerThanOneExp(real_input1_multiplier, &input1_multiplier, &input1_shift);
- quantizeMultiplierSmallerThanOneExp(real_input2_multiplier, &input2_multiplier, &input2_shift);
- quantizeMultiplierSmallerThanOneExp(real_output_multiplier, &output_multiplier, &output_shift);
-
- int32_t activation_min{};
- int32_t activation_max{};
- calculateActivationRangeQuantized(_params.activation, output(), &activation_min, &activation_max);
-
- auto fn = [input1_multiplier, input1_shift, //
- input2_multiplier, input2_shift, //
- output_multiplier, output_shift, //
- activation_min, activation_max](int16_t input1_val, int16_t input2_val) {
- const int32_t shifted_input1_val = static_cast<int32_t>(input1_val) << left_shift;
- const int32_t shifted_input2_val = static_cast<int32_t>(input2_val) << left_shift;
- const int32_t scaled_input1_val = tflite::MultiplyByQuantizedMultiplierSmallerThanOneExp(
- shifted_input1_val, input1_multiplier, input1_shift);
- const int32_t scaled_input2_val = tflite::MultiplyByQuantizedMultiplierSmallerThanOneExp(
- shifted_input2_val, input2_multiplier, input2_shift);
- const int32_t raw_sum = scaled_input1_val + scaled_input2_val;
- const int32_t raw_output = tflite::MultiplyByQuantizedMultiplierSmallerThanOneExp(
- raw_sum, output_multiplier, output_shift);
- const int32_t clamped_output = std::min(activation_max, std::max(activation_min, raw_output));
- return static_cast<int16_t>(clamped_output);
- };
-
- BinaryOpBroadcastSlow(getTensorShape(input1()), getTensorData<int16_t>(input1()),
- getTensorShape(input2()), getTensorData<int16_t>(input2()),
- getTensorShape(output()), getTensorData<int16_t>(output()), fn);
-}
-
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Add.h b/onert-micro/luci-interpreter/src/kernels/Add.h
deleted file mode 100644
index f9217173a..000000000
--- a/onert-micro/luci-interpreter/src/kernels/Add.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_ADD_H
-#define LUCI_INTERPRETER_KERNELS_ADD_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Add : public KernelWithParams<AddParams>
-{
-public:
- Add(const Tensor *input1, const Tensor *input2, Tensor *output, const AddParams &params);
-
- const Tensor *input1() const { return _inputs[0]; }
- const Tensor *input2() const { return _inputs[1]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-
-private:
- void evalFloat() const;
- template <typename T> void evalInteger() const;
- void evalQuantized() const;
- void evalQuantizedS16() const;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_ADD_H
diff --git a/onert-micro/luci-interpreter/src/kernels/Add.test.cpp b/onert-micro/luci-interpreter/src/kernels/Add.test.cpp
index b8b1c3089..6df81d3fe 100644
--- a/onert-micro/luci-interpreter/src/kernels/Add.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Add.test.cpp
@@ -15,14 +15,15 @@
* limitations under the License.
*/
-#include "kernels/Add.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/add/FloatAddKernel.h"
+#include "luci_interpreter/test_models/add/IntAddKernel.h"
+#include "luci_interpreter/test_models/add/NegAddKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
@@ -30,328 +31,136 @@ using namespace testing;
class AddTest : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-// for quantized Add, the error shouldn't exceed step
-float GetTolerance(float min, float max)
+template <typename T> std::vector<T> checkAddKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- float kQuantizedStep = (max - min) / 255.0;
- return kQuantizedStep;
-}
-
-TEST_F(AddTest, Uint8)
-{
- std::initializer_list<int32_t> base_shape = {2, 3, 1, 2};
- std::initializer_list<float> base_data = {-0.3f, 2.3f, 0.9f, 0.5f, 0.8f, -1.1f,
- 1.2f, 2.8f, -1.6f, 0.0f, 0.7f, -2.2f};
- std::initializer_list<int32_t> test_shapes[] = {
- {1, 1, 3, 2}, {1, 3, 1, 2}, {2, 1, 3, 1}, {2, 3, 1, 1}};
- std::initializer_list<float> test_data = {0.2f, 0.3f, -0.4f, 0.5f, 1.0f, 0.9f};
- std::initializer_list<int32_t> output_shapes[] = {
- {2, 3, 3, 2}, {2, 3, 1, 2}, {2, 3, 3, 2}, {2, 3, 1, 2}};
- std::vector<std::vector<float>> output_data = {
- {-0.1f, 2.6f, -0.7f, 2.8f, 0.7f, 3.0f, 1.1f, 0.8f, 0.5f, 1.0f, 1.9f, 1.4f,
- 1.0f, -0.8f, 0.4f, -0.6f, 1.8f, -0.2f, 1.4f, 3.0f, 0.8f, 3.0f, 2.2f, 3.0f,
- -1.4f, 0.3f, -2.0f, 0.5f, -0.6f, 0.9f, 0.9f, -1.9f, 0.3f, -1.7f, 1.7f, -1.3f},
- {-0.1f, 2.6f, 0.5f, 1.0f, 1.8f, -0.2f, 1.4f, 3.0f, -2.0f, 0.5f, 1.7f, -1.3f},
- {-0.1f, 2.5f, 0.0f, 2.6f, -0.7f, 1.9f, 1.1f, 0.7f, 1.2f, 0.8f, 0.5f, 0.1f,
- 1.0f, -0.9f, 1.1f, -0.8f, 0.4f, -1.5f, 1.7f, 3.0f, 2.2f, 3.0f, 2.1f, 3.0f,
- -1.1f, 0.5f, -0.6f, 1.0f, -0.7f, 0.9f, 1.2f, -1.7f, 1.7f, -1.2f, 1.6f, -1.3f},
- {-0.1f, 2.5f, 1.2f, 0.8f, 0.4f, -1.5f, 1.7f, 3.0f, -0.6f, 1.0f, 1.6f, -1.3f}};
- float kQuantizedTolerance = GetTolerance(-3.f, 3.f);
- std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(-3.f, 3.f);
- for (int i = 0; i < output_data.size(); i++)
- {
- Tensor input1_tensor = makeInputTensor<DataType::U8>(
- base_shape, quant_param.first, quant_param.second, base_data, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::U8>(
- test_shapes[i], quant_param.first, quant_param.second, test_data, _memory_manager.get());
- Tensor output_tensor =
- makeOutputTensor(getElementType<uint8_t>(), quant_param.first, quant_param.second);
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- AddParams params{};
- params.activation = Activation::NONE;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- Add kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 2);
- EXPECT_THAT(dequantizeTensorData(output_tensor),
- FloatArrayNear(output_data[i], kQuantizedTolerance));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shapes[i]));
+ // set left input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
}
- // Re-run with exchanged inputs.
- for (int i = 0; i < output_data.size(); i++)
+
+ // set right input data
{
- Tensor input1_tensor = makeInputTensor<DataType::U8>(
- test_shapes[i], quant_param.first, quant_param.second, test_data, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::U8>(
- base_shape, quant_param.first, quant_param.second, base_data, _memory_manager.get());
- Tensor output_tensor =
- makeOutputTensor(getElementType<uint8_t>(), quant_param.first, quant_param.second);
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(1));
+ std::copy(test_data_base->get_input_data_by_index(1).begin(),
+ test_data_base->get_input_data_by_index(1).end(), input_tensor_data);
+ }
- AddParams params{};
- params.activation = Activation::NONE;
+ runtime_module.execute();
- Add kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
- EXPECT_THAT(dequantizeTensorData(output_tensor),
- FloatArrayNear(output_data[i], kQuantizedTolerance));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shapes[i]));
- }
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST_F(AddTest, Float)
+TEST_F(AddTest, Float_P)
{
- Shape base_shape = {2, 3, 1, 2};
- std::vector<Shape> test_shapes{{1, 1, 3, 2}, {1, 3, 1, 2}, {2, 1, 3, 1}, {2, 3, 1, 1}};
- std::vector<std::vector<float>> test_outputs = {
- {0.0f, 2.6f, 0.0f, 2.8f, 0.7f, 3.2f, 1.1f, 0.8f, 0.5f, 1.0f, 1.9f, 1.4f,
- 1.0f, 0.0f, 0.4f, 0.0f, 1.8f, 0.0f, 1.4f, 3.1f, 0.8f, 3.3f, 2.2f, 3.7f,
- 0.0f, 0.3f, 0.0f, 0.5f, 0.0f, 0.9f, 0.9f, 0.0f, 0.3f, 0.0f, 1.7f, 0.0f},
- {0.0f, 2.6f, 0.5f, 1.0f, 1.8f, 0.0f, 1.4f, 3.1f, 0.0f, 0.5f, 1.7f, 0.0f},
- {0.0f, 2.5f, 0.0f, 2.6f, 0.0f, 1.9f, 1.1f, 0.7f, 1.2f, 0.8f, 0.5f, 0.1f,
- 1.0f, 0.0f, 1.1f, 0.0f, 0.4f, 0.0f, 1.7f, 3.3f, 2.2f, 3.8f, 2.1f, 3.7f,
- 0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.9f, 1.2f, 0.0f, 1.7f, 0.0f, 1.6f, 0.0f},
- {0.0f, 2.5f, 1.2f, 0.8f, 0.4f, 0.0f, 1.7f, 3.3f, 0.0f, 1.0f, 1.6f, 0.0f}};
- std::vector<float> input1_data{-0.3f, 2.3f, 0.9f, 0.5f, 0.8f, -1.1f,
- 1.2f, 2.8f, -1.6f, 0.0f, 0.7f, -2.2f};
- std::vector<float> input2_data{0.2f, 0.3f, -0.4f, 0.5f, 1.0f, 0.9f};
- for (size_t i = 0; i < test_shapes.size(); ++i)
+ // No broadcast
{
- Tensor input1_tensor =
- makeInputTensor<DataType::FLOAT32>(base_shape, input1_data, _memory_manager.get());
- Tensor input2_tensor =
- makeInputTensor<DataType::FLOAT32>(test_shapes[i], input2_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- AddParams params{};
- params.activation = Activation::RELU;
-
- Add kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(test_outputs[i], 0.0001f))
- << "With shape number " << i;
+ const bool is_with_broadcast = false;
+ test_kernel::TestDataFloatAdd test_data_float_add_no_broadcasting(is_with_broadcast);
+ std::vector<float> output_data_vector = checkAddKernel(&test_data_float_add_no_broadcasting);
+ EXPECT_THAT(output_data_vector,
+ kernels::testing::FloatArrayNear(
+ test_data_float_add_no_broadcasting.get_output_data_by_index(0), 0.0001f));
}
- // Re-run with exchanged inputs.
- for (size_t i = 0; i < test_shapes.size(); ++i)
+ // With broadcast
{
- Tensor input1_tensor =
- makeInputTensor<DataType::FLOAT32>(test_shapes[i], input2_data, _memory_manager.get());
- Tensor input2_tensor =
- makeInputTensor<DataType::FLOAT32>(base_shape, input1_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- AddParams params{};
- params.activation = Activation::RELU;
-
- Add kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(test_outputs[i], 0.0001f))
- << "With shape number " << i;
+ const bool is_with_broadcast = true;
+ test_kernel::TestDataFloatAdd test_data_float_add_with_broadcasting(is_with_broadcast);
+ std::vector<float> output_data_vector = checkAddKernel(&test_data_float_add_with_broadcasting);
+ EXPECT_THAT(output_data_vector,
+ kernels::testing::FloatArrayNear(
+ test_data_float_add_with_broadcasting.get_output_data_by_index(0), 0.0001f));
}
}
-template <loco::DataType DType> void CheckInteger(luci_interpreter::IMemoryManager *memory_manager)
+TEST_F(AddTest, INT64_P)
{
- using dtype = typename loco::DataTypeImpl<DType>::Type;
- Shape base_shape = {2, 3, 1, 2};
- std::vector<Shape> test_shapes{{1, 1, 3, 2}, {1, 3, 1, 2}, {2, 1, 3, 1}, {2, 3, 1, 1}};
- std::vector<std::vector<dtype>> test_outputs = {
- {3, 3, 0, 1, 0, 8, 5, 1, 0, 0, 2, 6, 8, 0, 1, 0, 5, 1,
- 5, 4, 0, 2, 2, 9, 11, 0, 4, 0, 8, 5, 11, 2, 4, 0, 8, 7},
- {3, 3, 0, 0, 5, 1, 5, 4, 4, 0, 8, 7},
- {3, 6, 0, 3, 0, 0, 5, 4, 2, 1, 0, 0, 8, 0, 5, 0, 1, 0,
- 0, 2, 2, 4, 7, 9, 6, 0, 8, 0, 13, 5, 6, 0, 8, 2, 13, 7},
- {3, 6, 2, 1, 1, 0, 0, 2, 8, 0, 13, 7}};
- std::vector<dtype> input1_data{-1, 2, 1, 0, 4, -5, 1, 3, 7, -1, 7, 1};
- std::vector<dtype> input2_data{4, 1, -3, -1, 1, 6};
- for (size_t i = 0; i < test_shapes.size(); ++i)
+ // No broadcast
{
- Tensor input1_tensor = makeInputTensor<DType>(base_shape, input1_data, memory_manager);
- Tensor input2_tensor = makeInputTensor<DType>(test_shapes[i], input2_data, memory_manager);
- Tensor output_tensor = makeOutputTensor(DType);
-
- AddParams params{};
- params.activation = Activation::RELU;
-
- Add kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<dtype>(output_tensor), test_outputs[i])
- << "With shape number " << i;
+ const bool is_with_broadcast = false;
+ test_kernel::TestData64IntAdd test_data_int64_add_no_broadcasting(is_with_broadcast);
+ const auto output_data_vector = checkAddKernel(&test_data_int64_add_no_broadcasting);
+ EXPECT_THAT(output_data_vector,
+ test_data_int64_add_no_broadcasting.get_output_data_by_index(0));
}
- // Re-run with exchanged inputs.
- for (size_t i = 0; i < test_shapes.size(); ++i)
+ // With broadcast
{
- Tensor input1_tensor = makeInputTensor<DType>(test_shapes[i], input2_data, memory_manager);
- Tensor input2_tensor = makeInputTensor<DType>(base_shape, input1_data, memory_manager);
- Tensor output_tensor = makeOutputTensor(DType);
-
- AddParams params{};
- params.activation = Activation::RELU;
-
- Add kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<dtype>(output_tensor), test_outputs[i])
- << "With shape number " << i;
+ const bool is_with_broadcast = true;
+ test_kernel::TestData64IntAdd test_data_int64_add_with_broadcasting(is_with_broadcast);
+ const auto output_data_vector = checkAddKernel(&test_data_int64_add_with_broadcasting);
+ EXPECT_THAT(output_data_vector,
+ test_data_int64_add_with_broadcasting.get_output_data_by_index(0));
}
-};
-
-TEST_F(AddTest, SInt32)
-{
- CheckInteger<loco::DataType::S32>(_memory_manager.get());
- SUCCEED();
-}
-
-TEST_F(AddTest, SInt64)
-{
- CheckInteger<loco::DataType::S64>(_memory_manager.get());
- SUCCEED();
}
-TEST_F(AddTest, SInt16)
+TEST_F(AddTest, INT32_P)
{
- Shape base_shape = {2, 3, 1, 2};
- std::vector<Shape> test_shapes{{1, 1, 3, 2}, {1, 3, 1, 2}, {2, 1, 3, 1}, {2, 3, 1, 1}};
- std::vector<std::vector<int32_t>> ref_output_shapes{
- {2, 3, 3, 2}, {2, 3, 1, 2}, {2, 3, 3, 2}, {2, 3, 1, 2}};
-
- std::vector<float> input1_data{-0.3f, 2.3f, 0.9f, 0.5f, 0.8f, -1.1f,
- 1.2f, 2.8f, -1.6f, 0.0f, 0.7f, -2.2f};
- std::vector<float> input2_data{0.2f, 0.3f, -0.4f, 0.5f, 1.0f, 0.9f};
- std::vector<std::vector<float>> ref_outputs = {
- {0.0f, 2.6f, 0.0f, 2.8f, 0.7f, 3.2f, 1.1f, 0.8f, 0.5f, 1.0f, 1.9f, 1.4f,
- 1.0f, 0.0f, 0.4f, 0.0f, 1.8f, 0.0f, 1.4f, 3.1f, 0.8f, 3.3f, 2.2f, 3.7f,
- 0.0f, 0.3f, 0.0f, 0.5f, 0.0f, 0.9f, 0.9f, 0.0f, 0.3f, 0.0f, 1.7f, 0.0f},
- {0.0f, 2.6f, 0.5f, 1.0f, 1.8f, 0.0f, 1.4f, 3.1f, 0.0f, 0.5f, 1.7f, 0.0f},
- {0.0f, 2.5f, 0.0f, 2.6f, 0.0f, 1.9f, 1.1f, 0.7f, 1.2f, 0.8f, 0.5f, 0.1f,
- 1.0f, 0.0f, 1.1f, 0.0f, 0.4f, 0.0f, 1.7f, 3.3f, 2.2f, 3.8f, 2.1f, 3.7f,
- 0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.9f, 1.2f, 0.0f, 1.7f, 0.0f, 1.6f, 0.0f},
- {0.0f, 2.5f, 1.2f, 0.8f, 0.4f, 0.0f, 1.7f, 3.3f, 0.0f, 1.0f, 1.6f, 0.0f}};
-
- for (size_t i = 0; i < test_shapes.size(); ++i)
+ // No broadcast
{
- Tensor input1_tensor = makeInputTensor<DataType::S16>(base_shape, 3.0 / 32767, 0, input1_data,
- _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::S16>(test_shapes[i], 1.0 / 32767, 0,
- input2_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S16, 4.0 / 32767, 0);
- const float tolerance = output_tensor.scale();
-
- AddParams params{};
- params.activation = Activation::RELU;
-
- Add kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor),
- ::testing::ElementsAreArray(ref_output_shapes[i]))
- << "With shape number " << i;
- EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_outputs[i], tolerance))
- << "With shape number " << i;
+ const bool is_with_broadcast = false;
+ test_kernel::TestData32IntAdd test_data_int32_add_no_broadcasting(is_with_broadcast);
+ const auto output_data_vector = checkAddKernel<int32_t>(&test_data_int32_add_no_broadcasting);
+ EXPECT_THAT(output_data_vector,
+ test_data_int32_add_no_broadcasting.get_output_data_by_index(0));
}
- // Re-run with exchanged inputs and different scales.
- for (size_t i = 0; i < test_shapes.size(); ++i)
+ // With broadcast
{
- Tensor input1_tensor = makeInputTensor<DataType::S16>(test_shapes[i], 2.0 / 32767, 0,
- input2_data, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::S16>(base_shape, 4.0 / 32767, 0, input1_data,
- _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S16, 5.0 / 32767, 0);
- const float tolerance = output_tensor.scale();
-
- AddParams params{};
- params.activation = Activation::RELU;
-
- Add kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor),
- ::testing::ElementsAreArray(ref_output_shapes[i]))
- << "With shape number " << i;
- EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_outputs[i], tolerance))
- << "With shape number " << i;
+ const bool is_with_broadcast = true;
+ test_kernel::TestData32IntAdd test_data_int32_add_with_broadcasting(is_with_broadcast);
+ const auto output_data_vector = checkAddKernel<int32_t>(&test_data_int32_add_with_broadcasting);
+ EXPECT_THAT(output_data_vector,
+ test_data_int32_add_with_broadcasting.get_output_data_by_index(0));
}
}
-TEST_F(AddTest, Input_Output_Type_NEG)
+TEST_F(AddTest, Input_type_mismatch_NEG)
{
- Tensor input1_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::S32>({1}, {2}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- AddParams params{};
- params.activation = Activation::RELU;
-
- Add kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(AddTest, Invalid_Output_Type_NEG)
-{
- Tensor input1_tensor = makeInputTensor<DataType::S64>({1}, {1}, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::S64>({1}, {2}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S32);
-
- AddParams params{};
- params.activation = Activation::RELU;
-
- Add kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::NegTestDataInputMismatchAddKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST_F(AddTest, Invalid_Input_Type_NEG)
+TEST_F(AddTest, No_quant_params_NEG)
{
- Tensor input1_tensor = makeInputTensor<DataType::U64>({1}, {1}, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::U64>({1}, {2}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U64);
-
- AddParams params{};
- params.activation = Activation::RELU;
-
- Add kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- EXPECT_ANY_THROW(kernel.execute());
+ test_kernel::NegTestDataNoQuantParamsS16AddKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST_F(AddTest, Invalid_Quantization_NEG)
-{
- Tensor input1_tensor = makeInputTensor<DataType::S16>({1}, {1}, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::S16>({1}, {2}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S16);
-
- AddParams params{};
- params.activation = Activation::NONE;
-
- Add kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
-}
+// TODO: add tests for U8 and S16
+// TODO: add tests for inplace optimizations for all types
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/AddN.cpp b/onert-micro/luci-interpreter/src/kernels/AddN.cpp
new file mode 100644
index 000000000..0df3c448b
--- /dev/null
+++ b/onert-micro/luci-interpreter/src/kernels/AddN.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Builders.h"
+#include "kernels/Utils.h"
+
+#include "PALAddN.h"
+
+namespace luci_interpreter
+{
+
+namespace
+{
+
+template <typename T>
+void evalGeneric(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+ const auto output_index = cur_op->outputs()->operator[](0);
+ assert(output_index != -1);
+ const auto output = runtime_graph->getCircleTensorByIndex(output_index);
+
+ const auto input_sizes = cur_op->inputs()->size();
+
+ auto input1_index = cur_op->inputs()->operator[](0);
+ const auto *tensor1 = runtime_graph->getCircleTensorByIndex(input1_index);
+
+ const int flat_size = Tensor::num_elements(tensor1);
+
+ std::vector<const T *> all_input_data;
+ for (int32_t i = 0; i < input_sizes; ++i)
+ {
+ auto input_index = cur_op->inputs()->operator[](i);
+ const auto *tensor = runtime_graph->getCircleTensorByIndex(input_index);
+
+ const auto *tensor_data = runtime_graph->getDataByTensor(tensor);
+ if (tensor_data == nullptr)
+ tensor_data = runtime_graph->getConstDataByTensor(tensor);
+
+ auto *data = reinterpret_cast<const T *>(tensor_data);
+ all_input_data.push_back(data);
+ }
+
+ auto *output_data = reinterpret_cast<T *>(runtime_graph->getDataByTensor(output));
+
+ luci_interpreter_pal::AddN(flat_size, input_sizes, all_input_data.data(), output_data);
+}
+
+} // namespace
+
+void configure_kernel_CircleAddN(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+ const int num_inputs = cur_op->inputs()->size();
+
+ LUCI_INTERPRETER_CHECK(num_inputs >= 2);
+ LUCI_INTERPRETER_CHECK(cur_op->outputs()->size() == 1);
+
+ const auto input1_index = cur_op->inputs()->operator[](0);
+ assert(input1_index != -1);
+
+ const auto input1_tensor = runtime_graph->getCircleTensorByIndex(input1_index);
+ assert(input1_tensor != nullptr);
+
+ for (int i = 1; i < num_inputs; ++i)
+ {
+ const auto input_index = cur_op->inputs()->operator[](i);
+ assert(input_index != -1);
+
+ const auto input_tensor = runtime_graph->getCircleTensorByIndex(input_index);
+ assert(input_tensor != nullptr);
+
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(input1_tensor) ==
+ Tensor::element_type(input_tensor));
+ LUCI_INTERPRETER_CHECK(Tensor::num_dims(input1_tensor) == Tensor::num_dims(input_tensor));
+ LUCI_INTERPRETER_CHECK(Tensor::num_elements(input1_tensor) ==
+ Tensor::num_elements(input_tensor));
+ }
+}
+
+void execute_kernel_CircleAddN(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+ const auto output_index = cur_op->outputs()->operator[](0);
+ assert(output_index != -1);
+ const auto output = runtime_graph->getCircleTensorByIndex(output_index);
+
+ switch (Tensor::element_type(output))
+ {
+#ifndef DIS_FLOAT
+ case DataType::FLOAT32:
+ {
+ evalGeneric<float>(cur_op, runtime_graph);
+ }
+ break;
+#endif // DIS_FLOAT
+ default:
+ assert(false && "Unsupported type.");
+ }
+}
+
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/AddN.test.cpp b/onert-micro/luci-interpreter/src/kernels/AddN.test.cpp
new file mode 100644
index 000000000..cee0bbc7b
--- /dev/null
+++ b/onert-micro/luci-interpreter/src/kernels/AddN.test.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/TestUtils.h"
+#include "luci_interpreter/test_models/add_n/FloatAddNKernel.h"
+#include "luci_interpreter/test_models/add_n/NegAddNKernel.h"
+
+#include "loader/ModuleLoader.h"
+
+namespace luci_interpreter
+{
+namespace
+{
+
+using namespace testing;
+
+class AddNTest : public ::testing::Test
+{
+ // Do nothing
+};
+
+template <typename T> std::vector<T> checkAddNKernel(test_kernel::TestDataBase<T> *test_data_base)
+{
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
+
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 3);
+
+ // set 1 input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
+
+ // set 2 input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(1));
+ std::copy(test_data_base->get_input_data_by_index(1).begin(),
+ test_data_base->get_input_data_by_index(1).end(), input_tensor_data);
+ }
+
+ // set 3 input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(2));
+ std::copy(test_data_base->get_input_data_by_index(2).begin(),
+ test_data_base->get_input_data_by_index(2).end(), input_tensor_data);
+ }
+
+ runtime_module.execute();
+
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
+
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
+}
+
+TEST_F(AddNTest, Float_P)
+{
+ test_kernel::TestDataFloatAddN test_data_kernel;
+ std::vector<float> output_data_vector = checkAddNKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+ test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(AddNTest, InputTypeMismatch_NEG)
+{
+ test_kernel::TestDataInputTypeMismatchAddN test_data_kernel;
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
+}
+
+} // namespace
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/ArgMax.cpp b/onert-micro/luci-interpreter/src/kernels/ArgMax.cpp
index 5ac4bcb1d..be6291c99 100644
--- a/onert-micro/luci-interpreter/src/kernels/ArgMax.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/ArgMax.cpp
@@ -15,127 +15,55 @@
* limitations under the License.
*/
-#include "kernels/ArgMax.h"
+#include "Builders.h"
#include "kernels/Utils.h"
-#include "PALArgMax.h"
+#include "TISOKernel.h"
+
+#include "PALArgMinMax.h"
namespace luci_interpreter
{
-namespace kernels
-{
-ArgMax::ArgMax(const Tensor *input, const Tensor *axis, Tensor *output, const ArgMaxParams &params)
- : KernelWithParams<ArgMaxParams>({input, axis}, {output}, params)
+void configure_kernel_CircleArgMax(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
+ // dim tensor must be a scalar or has one element
+ LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.input2()) == 0 or
+ Tensor::num_elements(kernel.input2()) == 1);
+ // value and output type must match
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.output()) == DataType::S32);
+
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input2()) == DataType::S32);
}
-void ArgMax::configure()
+void execute_kernel_CircleArgMax(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- assert(axis()->element_type() == DataType::S32 || axis()->element_type() == DataType::S64);
- assert(input()->shape().num_dims() >= 1);
- const Shape &input_shape = input()->shape();
- const int num_dims = input_shape.num_dims();
- Shape output_shape(num_dims - 1);
-
- // If axis value is negative, then update by adding input_shape's num_dims.
- // If updated value also negative, then assert.
- assert(axis()->shape().num_elements() == 1);
- int axis_value = getTensorData<int32_t>(axis())[0];
- if (axis_value < 0)
- axis_value = axis_value + num_dims;
- assert(axis_value >= 0);
-
- int j = 0;
- for (int i = 0; i < num_dims; i++)
- {
- if (i == axis_value)
- continue;
- output_shape.dim(j++) = input_shape.dim(i);
- }
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
- assert(output()->element_type() == _params.output_type);
+ const circle::Tensor *input = kernel.input1();
+ const circle::Tensor *output = kernel.output();
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(output_shape);
-}
-
-void ArgMax::execute() const
-{
+ kernels::TISOData tiso_data = kernel.readData();
+ const auto input_data = tiso_data.input1_data;
+ const auto axis_data = tiso_data.input2_data;
+ auto output_data = tiso_data.output_data;
-#define TF_LITE_ARG_MAX(data_type, axis_type, output_type) \
- luci_interpreter_pal::ArgMinMax(getTensorShape(input()), getTensorData<data_type>(input()), \
- getTensorData<axis_type>(axis()), getTensorShape(output()), \
- getTensorData<output_type>(output()), std::greater<data_type>())
- if (axis()->element_type() == DataType::S32)
- {
- switch (_params.output_type)
- {
- case DataType::S32:
- switch (input()->element_type())
- {
- case DataType::FLOAT32:
- TF_LITE_ARG_MAX(float, int32_t, int32_t);
- break;
- case DataType::U8:
- TF_LITE_ARG_MAX(uint8_t, int32_t, int32_t);
- break;
- default:
- assert(false && "Unsupported input type.");
- }
- break;
- case DataType::S64:
- switch (input()->element_type())
- {
- case DataType::FLOAT32:
- TF_LITE_ARG_MAX(float, int32_t, int64_t);
- break;
- case DataType::U8:
- TF_LITE_ARG_MAX(uint8_t, int32_t, int64_t);
- break;
- default:
- assert(false && "Unsupported input type.");
- }
- break;
- default:
- assert(false && "Unsupported output type.");
- }
- }
- else
+ switch (Tensor::element_type(input))
{
- switch (_params.output_type)
+#ifndef DIS_FLOAT
+ case DataType::FLOAT32:
{
- case DataType::S32:
- switch (input()->element_type())
- {
- case DataType::FLOAT32:
- TF_LITE_ARG_MAX(float, int64_t, int32_t);
- break;
- case DataType::U8:
- TF_LITE_ARG_MAX(uint8_t, int64_t, int32_t);
- break;
- default:
- assert(false && "Unsupported input type.");
- }
- break;
- case DataType::S64:
- switch (input()->element_type())
- {
- case DataType::FLOAT32:
- TF_LITE_ARG_MAX(float, int64_t, int64_t);
- break;
- case DataType::U8:
- TF_LITE_ARG_MAX(uint8_t, int64_t, int64_t);
- break;
- default:
- assert(false && "Unsupported input type.");
- }
- break;
- default:
- assert(false && "Unsupported output type.");
+ luci_interpreter_pal::ArgMinMax(
+ kernels::getTensorRuntimeShape(input, runtime_graph),
+ kernels::getTensorData<float>(input_data), kernels::getTensorData<int32_t>(axis_data),
+ kernels::getTensorRuntimeShape(output, runtime_graph),
+ kernels::getTensorData<int32_t>(output_data), std::greater<float>());
}
+ break;
+#endif // DIS_FLOAT
+ default:
+ assert(false && "Unsupported ArgMax input type");
}
-#undef TF_LITE_ARG_MAX
}
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/ArgMax.h b/onert-micro/luci-interpreter/src/kernels/ArgMax.h
deleted file mode 100644
index 0ee812d05..000000000
--- a/onert-micro/luci-interpreter/src/kernels/ArgMax.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_ARGMAX_H
-#define LUCI_INTERPRETER_KERNELS_ARGMAX_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class ArgMax : public KernelWithParams<ArgMaxParams>
-{
-public:
- ArgMax(const Tensor *input, const Tensor *axis, Tensor *output, const ArgMaxParams &params);
-
- const Tensor *input() const { return _inputs[0]; }
- const Tensor *axis() const { return _inputs[1]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_ARGMAX_H
diff --git a/onert-micro/luci-interpreter/src/kernels/ArgMax.test.cpp b/onert-micro/luci-interpreter/src/kernels/ArgMax.test.cpp
index 208987835..297ae2940 100644
--- a/onert-micro/luci-interpreter/src/kernels/ArgMax.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/ArgMax.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,109 +14,73 @@
* limitations under the License.
*/
-#include "kernels/ArgMax.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/argmax/FloatArgMaxKernel.h"
+#include "luci_interpreter/test_models/argmax/NegArgMaxKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
using namespace testing;
-template <typename T1, typename T2>
-void Check(std::initializer_list<int32_t> input_shape,
- std::initializer_list<int32_t> dimension_shape,
- std::initializer_list<int32_t> output_shape, std::initializer_list<T1> input_data,
- std::initializer_list<int32_t> dimension_data, std::initializer_list<T2> output_data)
+class ArgMaxTest : public ::testing::Test
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- constexpr DataType element_type = getElementType<T1>();
- Tensor input_tensor =
- makeInputTensor<element_type>(input_shape, input_data, memory_manager.get());
- Tensor dimension_tensor =
- makeInputTensor<DataType::S32>(dimension_shape, dimension_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(getElementType<T2>());
+ // Do nothing
+};
- ArgMaxParams params{};
- params.output_type = getElementType<T2>();
- ArgMax kernel(&input_tensor, &dimension_tensor, &output_tensor, params);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+template <typename T, typename O>
+std::vector<O> checkKernel(test_kernel::TestDataBase<T, O> *test_data_base)
+{
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- EXPECT_THAT(extractTensorData<T2>(output_tensor), ::testing::ElementsAreArray(output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), output_shape);
-}
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
-template <typename T> class ArgMaxTest : public ::testing::Test
-{
-};
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
-using DataTypes = ::testing::Types<float, uint8_t>;
-TYPED_TEST_SUITE(ArgMaxTest, DataTypes);
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
-TYPED_TEST(ArgMaxTest, Simple)
-{
- Check<TypeParam, int32_t>(/*input_shape=*/{1, 1, 1, 4}, /*dimension_shape=*/{},
- /*output_shape=*/{1, 1, 1},
- /*input_data=*/
- {
- 1, 9, 7, 3, //
- },
- /*dimension_data=*/{3}, /*output_data=*/{1});
- Check<TypeParam, int64_t>(/*input_shape=*/{1, 1, 1, 4}, /*dimension_shape=*/{},
- /*output_shape=*/{1, 1, 1},
- /*input_data=*/
- {
- 1, 9, 7, 3, //
- },
- /*dimension_data=*/{3}, /*output_data=*/{1});
+ runtime_module.execute();
+
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
+
+ O *output_data = reinterpret_cast<O *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(O));
+ std::vector<O> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TYPED_TEST(ArgMaxTest, MultiDimensions)
+TEST_F(ArgMaxTest, MainTest_P)
{
- Check<TypeParam, int32_t>(/*input_shape=*/{1, 1, 2, 4}, /*dimension_shape=*/{},
- /*output_shape=*/{1, 1, 2},
- /*input_data=*/
- {
- 1, 2, 7, 8, //
- 1, 9, 7, 3, //
- },
- /*dimension_data=*/{3}, /*output_data=*/{3, 1});
- Check<TypeParam, int64_t>(/*input_shape=*/{1, 1, 2, 4}, /*dimension_shape=*/{},
- /*output_shape=*/{1, 1, 2},
- /*input_data=*/
- {
- 1, 2, 7, 8, //
- 1, 9, 7, 3, //
- },
- /*dimension_data=*/{3}, /*output_data=*/{3, 1});
+ test_kernel::TestDataFloatArgMax test_data_kernel;
+ std::vector<int32_t> output_data_vector = checkKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-TEST(ArgMaxTest, UnsupportedType_NEG)
+TEST_F(ArgMaxTest, Input_output_type_mismatch_NEG)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({1, 1, 2, 4},
- {
- 1, 2, 7, 8, //
- 1, 9, 7, 3, //
- },
- memory_manager.get());
- Tensor dimension_tensor = makeInputTensor<DataType::S32>({}, {3}, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U8);
-
- ArgMaxParams params{};
- params.output_type = DataType::U8;
- ArgMax kernel(&input_tensor, &dimension_tensor, &output_tensor, params);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- EXPECT_ANY_THROW(kernel.execute());
+ test_kernel::TestDataOutputWrongOutputArgMax test_data_kernel;
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/ArgMin.cpp b/onert-micro/luci-interpreter/src/kernels/ArgMin.cpp
new file mode 100644
index 000000000..ed1249602
--- /dev/null
+++ b/onert-micro/luci-interpreter/src/kernels/ArgMin.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Builders.h"
+#include "kernels/Utils.h"
+#include "TISOKernel.h"
+
+#include "PALArgMinMax.h"
+
+namespace luci_interpreter
+{
+
+// TODO: reduce code duplication with arg max
+void configure_kernel_CircleArgMin(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
+ // dim tensor must be a scalar or has one element
+ LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.input2()) == 0 or
+ Tensor::num_elements(kernel.input2()) == 1);
+ // value and output type must match
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.output()) == DataType::S32);
+
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input2()) == DataType::S32);
+}
+
+void execute_kernel_CircleArgMin(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
+
+ const circle::Tensor *input = kernel.input1();
+ const circle::Tensor *output = kernel.output();
+
+ kernels::TISOData tiso_data = kernel.readData();
+ const auto input_data = tiso_data.input1_data;
+ const auto axis_data = tiso_data.input2_data;
+ auto output_data = tiso_data.output_data;
+
+ switch (Tensor::element_type(input))
+ {
+#ifndef DIS_FLOAT
+ case DataType::FLOAT32:
+ {
+ luci_interpreter_pal::ArgMinMax(
+ kernels::getTensorRuntimeShape(input, runtime_graph),
+ kernels::getTensorData<float>(input_data), kernels::getTensorData<int32_t>(axis_data),
+ kernels::getTensorRuntimeShape(output, runtime_graph),
+ kernels::getTensorData<int32_t>(output_data), std::less<float>());
+ }
+ break;
+#endif // DIS_FLOAT
+ default:
+ assert(false && "Unsupported ArgMax input type");
+ }
+}
+
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/ArgMin.test.cpp b/onert-micro/luci-interpreter/src/kernels/ArgMin.test.cpp
new file mode 100644
index 000000000..b2756637b
--- /dev/null
+++ b/onert-micro/luci-interpreter/src/kernels/ArgMin.test.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/TestUtils.h"
+#include "luci_interpreter/test_models/argmin/FloatArgMinKernel.h"
+#include "luci_interpreter/test_models/argmin/NegArgMinKernel.h"
+
+#include "loader/ModuleLoader.h"
+
+namespace luci_interpreter
+{
+namespace
+{
+
+using namespace testing;
+
+class ArgMinTest : public ::testing::Test
+{
+ // Do nothing
+};
+
+template <typename T, typename O>
+std::vector<O> checkKernel(test_kernel::TestDataBase<T, O> *test_data_base)
+{
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
+
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
+
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
+
+ runtime_module.execute();
+
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
+
+ O *output_data = reinterpret_cast<O *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(O));
+ std::vector<O> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
+}
+
+TEST_F(ArgMinTest, MainTest_P)
+{
+ test_kernel::TestDataFloatArgMin test_data_kernel;
+ std::vector<int32_t> output_data_vector = checkKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(ArgMinTest, Input_output_type_mismatch_NEG)
+{
+ test_kernel::TestDataOutputWrongOutputArgMin test_data_kernel;
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
+}
+
+} // namespace
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/AveragePool2D.cpp b/onert-micro/luci-interpreter/src/kernels/AveragePool2D.cpp
index 6dd81aba5..ccdda8406 100644
--- a/onert-micro/luci-interpreter/src/kernels/AveragePool2D.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/AveragePool2D.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,180 +14,87 @@
* limitations under the License.
*/
-#include "kernels/AveragePool2D.h"
+#include "Builders.h"
#include "kernels/Utils.h"
-
-#include "PALAveragePool2d.h"
+#include "PALAveragePool2D.h"
namespace luci_interpreter
{
-namespace kernels
+// TODO: reduce code duplication with MaxPool2D
+void configure_kernel_CircleAveragePool2D(const circle::Operator *cur_op,
+ BaseRuntimeGraph *runtime_graph)
{
+ const auto input_index = cur_op->inputs()->operator[](0);
+ const auto output_index = cur_op->outputs()->operator[](0);
-AveragePool2D::AveragePool2D(const Tensor *input, Tensor *output, Tensor *scratchpad,
- const Pool2DParams &params)
- : KernelWithParams<Pool2DParams>({input}, {output, scratchpad}, params)
-{
-}
+ assert(input_index != -1);
+ assert(output_index != -1);
-void AveragePool2D::configure()
-{
- if (input()->element_type() != output()->element_type())
- {
- assert(false && "Input Tensor and Output Tensor Type must be same");
- }
- if (input()->shape().num_dims() != 4)
- {
- assert(false && "Input Tensor Shape must be 4-D");
- }
- const Shape &input_shape = input()->shape();
-
- const int32_t batches = input_shape.dim(0);
- const int32_t input_height = input_shape.dim(1);
- const int32_t input_width = input_shape.dim(2);
- const int32_t depth = input_shape.dim(3);
-
- const int32_t output_height =
- computeOutputSize(_params.padding, input_height, _params.filter_height, _params.stride_height);
- const int32_t output_width =
- computeOutputSize(_params.padding, input_width, _params.filter_width, _params.stride_width);
-
- _padding_height =
- computePadding(_params.stride_height, 1, input_height, _params.filter_height, output_height);
- _padding_width =
- computePadding(_params.stride_width, 1, input_width, _params.filter_width, output_width);
- if (input()->element_type() == DataType::U8)
- {
- LUCI_INTERPRETER_CHECK(std::abs(output()->scale() - input()->scale()) <= 1.0e-6);
- LUCI_INTERPRETER_CHECK(output()->zero_point() == input()->zero_point());
- }
- else if (input()->element_type() == DataType::S16)
- {
- LUCI_INTERPRETER_CHECK(std::abs(output()->scale() - input()->scale()) <= 1.0e-6);
- LUCI_INTERPRETER_CHECK(input()->zero_point() == 0 && output()->zero_point() == 0);
- }
- else if (input()->element_type() == DataType::S8)
- {
- LUCI_INTERPRETER_CHECK(std::abs(output()->scale() - input()->scale()) <= 1.0e-6);
- LUCI_INTERPRETER_CHECK(output()->zero_point() == input()->zero_point());
- }
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize({batches, output_height, output_width, depth});
+ const auto input = runtime_graph->getCircleTensorByIndex(input_index);
+ const auto output = runtime_graph->getCircleTensorByIndex(output_index);
- auto scratchpad = getOutputTensors()[1];
- luci_interpreter_pal::SetupScratchpadTensor(scratchpad, input()->element_type(),
- getTensorShape(input()), getTensorShape(output()));
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(input) == Tensor::element_type(output));
+ assert(Tensor::num_dims(input) == 4);
}
-void AveragePool2D::execute() const
+void execute_kernel_CircleAveragePool2D(const circle::Operator *cur_op,
+ BaseRuntimeGraph *runtime_graph)
{
- switch (input()->element_type())
- {
- case DataType::FLOAT32:
- evalFloat();
- break;
- case DataType::U8:
- evalQuantized();
- break;
- case DataType::S16:
- evalSInt16();
- break;
- case DataType::S8:
- evalSInt8();
- break;
- default:
- assert(false && "Unsupported type.");
- }
-}
+ const auto input_index = cur_op->inputs()->operator[](0);
+ const auto output_index = cur_op->outputs()->operator[](0);
+
+ assert(input_index != -1);
+ assert(output_index != -1);
+
+ const auto input = runtime_graph->getCircleTensorByIndex(input_index);
+ auto output = runtime_graph->getCircleTensorByIndex(output_index);
+
+ const auto *options = cur_op->builtin_options_as_Pool2DOptions();
+
+ const int32_t input_height = Tensor::dim(input, 1);
+ const int32_t input_width = Tensor::dim(input, 2);
+
+ const int32_t output_height = kernels::computeOutputSize(
+ luci_padding(options->padding()), input_height, options->filter_height(), options->stride_h());
+ const int32_t output_width = kernels::computeOutputSize(
+ luci_padding(options->padding()), input_width, options->filter_width(), options->stride_w());
+
+ const auto padding_height = kernels::computePadding(options->stride_h(), 1, input_height,
+ options->filter_height(), output_height);
+ const auto padding_width = kernels::computePadding(options->stride_w(), 1, input_width,
+ options->filter_width(), output_width);
+
+ const auto *input_data = runtime_graph->getDataByTensor(input);
+ auto *output_data = runtime_graph->getDataByTensor(output);
-void AveragePool2D::evalFloat() const
-{
float activation_min{};
float activation_max{};
- calculateActivationRange(_params.activation, &activation_min, &activation_max);
-
- tflite::PoolParams params{};
- params.padding_values.height = _padding_height;
- params.padding_values.width = _padding_width;
- params.stride_height = _params.stride_height;
- params.stride_width = _params.stride_width;
- params.filter_height = _params.filter_height;
- params.filter_width = _params.filter_width;
+ kernels::calculateActivationRange(luci_actfunc(options->fused_activation_function()),
+ &activation_min, &activation_max);
+ luci_interpreter_pal::PoolParams params{};
+ params.padding_values.height = padding_height;
+ params.padding_values.width = padding_width;
+ params.stride_height = options->stride_h();
+ params.stride_width = options->stride_w();
+ params.filter_height = options->filter_height();
+ params.filter_width = options->filter_width();
params.float_activation_min = activation_min;
params.float_activation_max = activation_max;
- tflite::reference_ops::AveragePool(params, getTensorShape(input()), getTensorData<float>(input()),
- getTensorShape(output()), getTensorData<float>(output()));
-}
-
-void AveragePool2D::evalQuantized() const
-{
- int32_t activation_min{};
- int32_t activation_max{};
- calculateActivationRangeQuantized(_params.activation, output(), &activation_min, &activation_max);
-
- tflite::PoolParams params{};
- params.padding_values.height = _padding_height;
- params.padding_values.width = _padding_width;
- params.stride_height = _params.stride_height;
- params.stride_width = _params.stride_width;
- params.filter_height = _params.filter_height;
- params.filter_width = _params.filter_width;
- params.quantized_activation_min = activation_min;
- params.quantized_activation_max = activation_max;
-
- tflite::reference_ops::AveragePool(params, getTensorShape(input()),
- getTensorData<uint8_t>(input()), getTensorShape(output()),
- getTensorData<uint8_t>(output()));
-}
-
-void AveragePool2D::evalSInt8() const
-{
- int32_t activation_min{};
- int32_t activation_max{};
- calculateActivationRangeQuantized(_params.activation, output(), &activation_min, &activation_max);
- tflite::PoolParams params{};
- params.padding_values.height = _padding_height;
- params.padding_values.width = _padding_width;
- params.stride_height = _params.stride_height;
- params.stride_width = _params.stride_width;
- params.filter_height = _params.filter_height;
- params.filter_width = _params.filter_width;
- params.quantized_activation_min = activation_min;
- params.quantized_activation_max = activation_max;
-
- auto scratchpad = getOutputTensors()[1];
- int8_t *scratchpad_data = nullptr;
- if (scratchpad->is_allocatable())
- scratchpad_data = scratchpad->data<int8_t>();
-
- luci_interpreter_pal::AveragePool<int8_t>(
- params, getTensorShape(input()), getTensorData<int8_t>(input()), getTensorShape(output()),
- getTensorData<int8_t>(output()), getTensorShape(scratchpad), scratchpad_data);
-}
-
-void AveragePool2D::evalSInt16() const
-{
- int32_t activation_min{};
- int32_t activation_max{};
- calculateActivationRangeQuantized(_params.activation, output(), &activation_min, &activation_max);
-
- tflite::PoolParams params{};
- params.padding_values.height = _padding_height;
- params.padding_values.width = _padding_width;
- params.stride_height = _params.stride_height;
- params.stride_width = _params.stride_width;
- params.filter_height = _params.filter_height;
- params.filter_width = _params.filter_width;
- params.quantized_activation_min = activation_min;
- params.quantized_activation_max = activation_max;
-
- tflite::reference_integer_ops::AveragePool(
- params, getTensorShape(input()), getTensorData<int16_t>(input()), //
- getTensorShape(output()), getTensorData<int16_t>(output()));
+ switch (Tensor::element_type(input))
+ {
+#ifndef DIS_FLOAT
+ case DataType::FLOAT32:
+ luci_interpreter_pal::AveragePool(
+ params, kernels::getTensorShape(input), kernels::getTensorData<float>(input_data),
+ kernels::getTensorShape(output), kernels::getTensorData<float>(output_data));
+ break;
+#endif // DIS_FLOAT
+ default:
+ assert(false && "Unsupported type.");
+ }
}
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/AveragePool2D.h b/onert-micro/luci-interpreter/src/kernels/AveragePool2D.h
deleted file mode 100644
index 9e26c35f5..000000000
--- a/onert-micro/luci-interpreter/src/kernels/AveragePool2D.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_AVERAGEPOOL2D_H
-#define LUCI_INTERPRETER_KERNELS_AVERAGEPOOL2D_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class AveragePool2D : public KernelWithParams<Pool2DParams>
-{
-public:
- AveragePool2D(const Tensor *input, Tensor *output, Tensor *scratchpad,
- const Pool2DParams &params);
-
- const Tensor *input() const { return _inputs[0]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-
-private:
- void evalFloat() const;
- void evalQuantized() const;
- void evalSInt16() const;
- void evalSInt8() const;
-
-private:
- int32_t _padding_height{};
- int32_t _padding_width{};
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_AVERAGEPOOL2D_H
diff --git a/onert-micro/luci-interpreter/src/kernels/AveragePool2D.test.cpp b/onert-micro/luci-interpreter/src/kernels/AveragePool2D.test.cpp
index 1bd058e74..6bc326453 100644
--- a/onert-micro/luci-interpreter/src/kernels/AveragePool2D.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/AveragePool2D.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,14 +14,14 @@
* limitations under the License.
*/
-#include "kernels/AveragePool2D.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/average_pool_2d/FloatAveragePool2DKernel.h"
+#include "luci_interpreter/test_models/average_pool_2d/NegAveragePool2DKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
@@ -30,255 +29,60 @@ using namespace testing;
class AveragePool2DTest : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-TEST_F(AveragePool2DTest, Float)
-{
- Shape input_shape{1, 3, 5, 1};
- std::vector<float> input_data{
- -4, -3, -2, -1, 0, //
- 1, 2, 3, 4, 5, //
- 6, 7, 8, 9, 10, //
- };
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
- Tensor scratchpad(DataType::FLOAT32, Shape({}), {}, "");
-
- Pool2DParams params{};
- params.padding = Padding::VALID;
- params.filter_height = 2;
- params.filter_width = 3;
- params.stride_height = 1;
- params.stride_width = 2;
- params.activation = Activation::RELU6;
-
- AveragePool2D kernel(&input_tensor, &output_tensor, &scratchpad, params);
- kernel.configure();
- _memory_manager->allocate_memory(scratchpad);
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- std::vector<float> ref_output_data{
- 0, 1.5, //
- 4.5, 6, //
- };
- EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 2, 1}));
-}
-
-TEST_F(AveragePool2DTest, Uint8_0)
-{
- std::vector<float> input_data{
- 0, -6, 12, 4, //
- -3, -2, 10, 7, //
- };
- std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(-15.9375f, 15.9375f);
- Tensor input_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, quant_param.first, quant_param.second, input_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.second);
- Tensor scratchpad(DataType::U8, Shape({}), {}, "");
-
- Pool2DParams params{};
- params.padding = Padding::VALID;
- params.filter_height = 2;
- params.filter_width = 2;
- params.stride_height = 2;
- params.stride_width = 2;
- params.activation = Activation::RELU6;
-
- AveragePool2D kernel(&input_tensor, &output_tensor, &scratchpad, params);
- kernel.configure();
- _memory_manager->allocate_memory(scratchpad);
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear({0.0, 6.0}));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 1, 2, 1}));
-}
-
-TEST_F(AveragePool2DTest, Uint8_1)
-{
- std::vector<float> input_data{
- 0, 6, 12, 4, //
- 3, 2, 10, 7, //
- };
-
- std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(-15.9375f, 15.9375f);
- Tensor input_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, quant_param.first, quant_param.second, input_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.second);
- Tensor scratchpad(DataType::U8, Shape({}), {}, "");
-
- Pool2DParams params{};
- params.padding = Padding::VALID;
- params.filter_height = 2;
- params.filter_width = 2;
- params.stride_height = 2;
- params.stride_width = 2;
- params.activation = Activation::RELU6;
-
- AveragePool2D kernel(&input_tensor, &output_tensor, &scratchpad, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- _memory_manager->allocate_memory(scratchpad);
- kernel.execute();
-
- EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear({2.75, 6.0}));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 1, 2, 1}));
-}
-
-TEST_F(AveragePool2DTest, SInt16)
-{
- Shape input_shape{1, 3, 5, 1};
- std::vector<int32_t> ref_output_shape{1, 2, 2, 1};
- std::vector<float> input_data{
- -4, -3, -2, -1, 0, //
- 1, 2, 3, 4, 5, //
- 6, 7, 8, 9, 10, //
- };
- std::vector<float> ref_output_data{
- 0, 1.5, //
- 4.5, 6, //
- };
- Tensor input_tensor =
- makeInputTensor<DataType::S16>(input_shape, 0.5, 0, input_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S16, 0.5, 0);
- Tensor scratchpad(DataType::S16, Shape({}), {}, "");
-
- Pool2DParams params{};
- params.padding = Padding::VALID;
- params.filter_height = 2;
- params.filter_width = 3;
- params.stride_height = 1;
- params.stride_width = 2;
- params.activation = Activation::RELU6;
-
- AveragePool2D kernel(&input_tensor, &output_tensor, &scratchpad, params);
- kernel.configure();
- _memory_manager->allocate_memory(scratchpad);
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
- EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
-}
-
-TEST_F(AveragePool2DTest, SInt8)
+template <typename T>
+std::vector<T> checkAveragePool2DKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- Shape input_shape{1, 4, 5, 1};
- std::vector<int32_t> ref_output_shape{1, 2, 2, 1};
- std::vector<float> input_data{-7, -3, 0, 2, -5, 12, -15, 3, 10, 5,
- 7, -6, -1, 9, -2, 0, -5, 11, -1, -7};
- std::vector<float> ref_output_data{
- 0, 2.5, //
- 1, 1.5, //
- };
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- std::pair<float, int32_t> quant_param = quantizationParams<int8_t>(-15.9375f, 15.9375f);
- Tensor input_tensor = makeInputTensor<DataType::S8>(
- input_shape, quant_param.first, quant_param.second, input_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S8, quant_param.first, quant_param.second);
- Tensor scratchpad(DataType::S8, Shape({}), {}, "");
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- Pool2DParams params{};
- params.padding = Padding::VALID;
- params.filter_height = 2;
- params.filter_width = 3;
- params.stride_height = 2;
- params.stride_width = 2;
- params.activation = Activation::RELU6;
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
- AveragePool2D kernel(&input_tensor, &output_tensor, &scratchpad, params);
- kernel.configure();
- _memory_manager->allocate_memory(scratchpad);
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
- EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
-}
+ runtime_module.execute();
-TEST_F(AveragePool2DTest, Invalid_Input_Shape_NEG)
-{
- Shape input_shape{1, 3, 5};
- std::vector<float> input_data{
- -4, -3, -2, -1, 0, //
- 1, 2, 3, 4, 5, //
- 6, 7, 8, 9, 10, //
- };
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
- Tensor scratchpad(DataType::FLOAT32, Shape({}), {}, "");
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
- Pool2DParams params{};
- params.padding = Padding::VALID;
- params.filter_height = 2;
- params.filter_width = 3;
- params.stride_height = 1;
- params.stride_width = 2;
- params.activation = Activation::RELU6;
-
- AveragePool2D kernel(&input_tensor, &output_tensor, &scratchpad, params);
- EXPECT_ANY_THROW(kernel.configure());
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST_F(AveragePool2DTest, In_Out_Type_NEG)
+TEST_F(AveragePool2DTest, Float_P)
{
- Shape input_shape{1, 3, 5, 1};
- std::vector<float> input_data{
- -4, -3, -2, -1, 0, //
- 1, 2, 3, 4, 5, //
- 6, 7, 8, 9, 10, //
- };
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U8);
- Tensor scratchpad(DataType::FLOAT32, Shape({}), {}, "");
-
- Pool2DParams params{};
- params.padding = Padding::VALID;
- params.filter_height = 2;
- params.filter_width = 3;
- params.stride_height = 1;
- params.stride_width = 2;
- params.activation = Activation::RELU6;
-
- AveragePool2D kernel(&input_tensor, &output_tensor, &scratchpad, params);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::TestDataFloatAveragePool2D test_data_kernel;
+ std::vector<float> output_data_vector = checkAveragePool2DKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+ test_data_kernel.get_output_data_by_index(0), 0.001f));
}
-TEST_F(AveragePool2DTest, Quant_Param_NEG)
+TEST_F(AveragePool2DTest, InputOutputTypeMismatch_NEG)
{
- std::vector<float> input_data{
- 0, -6, 12, 4, //
- -3, -2, 10, 7, //
- };
-
- std::pair<float, int32_t> quant_param1 = quantizationParams<uint8_t>(-15.9375f, 15.9375f);
- std::pair<float, int32_t> quant_param2 = quantizationParams<uint8_t>(-7.875f, 7.875f);
- Tensor input_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, quant_param1.first, quant_param1.second, input_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param2.first, quant_param2.second);
- Tensor scratchpad(DataType::U8, Shape({}), {}, "");
-
- Pool2DParams params{};
- params.padding = Padding::VALID;
- params.filter_height = 2;
- params.filter_width = 2;
- params.stride_height = 2;
- params.stride_width = 2;
- params.activation = Activation::RELU6;
-
- AveragePool2D kernel(&input_tensor, &output_tensor, &scratchpad, params);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::NegTestDataInputOutputTypeMismatchAveragePool2DKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/BatchMatMul.h b/onert-micro/luci-interpreter/src/kernels/BatchMatMul.h
index 84e93edf7..744f49795 100644
--- a/onert-micro/luci-interpreter/src/kernels/BatchMatMul.h
+++ b/onert-micro/luci-interpreter/src/kernels/BatchMatMul.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/BatchMatMul.test.cpp b/onert-micro/luci-interpreter/src/kernels/BatchMatMul.test.cpp
index 90db77b76..edfa3a685 100644
--- a/onert-micro/luci-interpreter/src/kernels/BatchMatMul.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/BatchMatMul.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.h b/onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.h
index 803cf29f1..57703ea5d 100644
--- a/onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.h
+++ b/onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.test.cpp b/onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.test.cpp
index fc936d118..52647a763 100644
--- a/onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/BinaryOpCommon.h b/onert-micro/luci-interpreter/src/kernels/BinaryOpCommon.h
index 2d2842a9e..1fd27ea63 100644
--- a/onert-micro/luci-interpreter/src/kernels/BinaryOpCommon.h
+++ b/onert-micro/luci-interpreter/src/kernels/BinaryOpCommon.h
@@ -18,55 +18,197 @@
#ifndef LUCI_INTERPRETER_KERNELS_BINARYOPUTILS_H
#define LUCI_INTERPRETER_KERNELS_BINARYOPUTILS_H
-#include "tensorflow/lite/kernels/internal/common.h"
-#include "tensorflow/lite/kernels/internal/types.h"
+#include "TISOKernel.h"
+#include "ProcessBroadcastShapes.h"
+
+#include "Utils.h"
namespace luci_interpreter
{
namespace kernels
{
-// Derived from tensorflow/lite/kernels/internal/reference/maximum_minimum.h (v2.3.0).
-template <typename T, typename Op, int N = 5>
-void BinaryOpBroadcastSlow(const tflite::RuntimeShape &unextended_input1_shape,
- const T *input1_data,
- const tflite::RuntimeShape &unextended_input2_shape,
- const T *input2_data,
- const tflite::RuntimeShape &unextended_output_shape, T *output_data,
- Op op)
+namespace
+{
+
+/**
+ * Fills activation min and max parameters depending on given data type and activation
+ *
+ * T is a template parameter, so after optimization this code left with only required if case
+ *
+ * @tparam T data type of arithmetic operation output tensor
+ * @param params tflite params to fill
+ * @param activation luci_interpreter::Activation of arithmetic operation
+ */
+template <typename T>
+void fillArithmeticActivationRange(luci_interpreter_pal::ArithmeticParams &p, Activation act)
+{
+ static_assert(one_of_types<T, float, int32_t, int64_t>(), "Unsupported dtype");
+
+ if (std::is_same<T, float>::value)
+ calculateActivationRange(act, &p.float_activation_min, &p.float_activation_max);
+ if (std::is_same<T, int32_t>::value)
+ calculateActivationRange(act, &p.quantized_activation_min, &p.quantized_activation_max);
+ else
+ calculateActivationRange(act, &p.int64_activation_min, &p.int64_activation_max);
+}
+
+} // namespace
+
+template <typename T, typename TISOFunc = nullptr_t, typename TISOBroadcastFunc = nullptr_t,
+ typename Options = nullptr_t>
+void evalTISOKernel(TISOFunc tiso_func, TISOBroadcastFunc tiso_broadcast_func,
+ kernels::TISOKernel *kernel, kernels::TISOData *kernel_data,
+ const Options *options, RuntimeShape &&input_shape_1,
+ RuntimeShape &&input_shape_2)
+{
+ const auto *output = kernel->output();
+
+ luci_interpreter_pal::ArithmeticParams params{};
+ fillArithmeticActivationRange<T>(params, luci_actfunc(options->fused_activation_function()));
+
+ const bool need_broadcast =
+ luci_interpreter_pal::ProcessBroadcastShapes(input_shape_1, input_shape_2, &params);
+
+ if (need_broadcast)
+ {
+ tiso_broadcast_func(params, input_shape_1, kernels::getTensorData<T>(kernel_data->input1_data),
+ input_shape_2, kernels::getTensorData<T>(kernel_data->input2_data),
+ kernels::getTensorShape(output),
+ kernels::getTensorData<T>(kernel_data->output_data));
+ }
+ else
+ {
+ const int flat_size = input_shape_1.flatSize();
+ tiso_func(params, flat_size, kernels::getTensorData<T>(kernel_data->input1_data),
+ kernels::getTensorData<T>(kernel_data->input2_data),
+ kernels::getTensorData<T>(kernel_data->output_data));
+ }
+}
+
+template <typename T, typename TISOFunc = nullptr_t, typename TISOBroadcastFunc = nullptr_t,
+ typename Options = nullptr_t>
+void evalTISOInplaceKernel(TISOFunc tiso_func, TISOBroadcastFunc tiso_broadcast_func,
+ kernels::TISOKernel *kernel, const Options *options,
+ RuntimeShape &&input_shape_1, RuntimeShape &&input_shape_2)
+{
+ uint8_t *inplace_data_ptr = nullptr;
+ circle::Tensor *input_inplace_tensor = nullptr;
+
+ kernels::TISOData kernel_data = kernel->readInplaceData(inplace_data_ptr, input_inplace_tensor);
+
+ evalTISOKernel<T, TISOFunc, TISOBroadcastFunc, Options>(
+ tiso_func, tiso_broadcast_func, kernel, &kernel_data, options, std::move(input_shape_1),
+ std::move(input_shape_2));
+
+ BaseRuntimeGraph *runtime_graph = kernel->runtime_graph();
+
+ runtime_graph->makeInplaceOperation(input_inplace_tensor, kernel->output());
+ if (input_inplace_tensor == kernel->input1())
+ {
+ runtime_graph->makeInplaceOperation(kernel->input2(), nullptr);
+ }
+ else
+ {
+ runtime_graph->makeInplaceOperation(kernel->input1(), nullptr);
+ }
+}
+
+#ifndef DIS_QUANT
+template <typename T, typename TISOFunc = nullptr_t, typename TISOBroadcastFunc = nullptr_t,
+ typename Options = nullptr_t>
+void evalTISOQuantizedKernel(TISOFunc tiso_func, TISOBroadcastFunc tiso_broadcast_func,
+ kernels::TISOKernel *kernel, kernels::TISOData *kernel_data,
+ const Options *options)
+{
+ const auto *input1 = kernel->input1();
+ const auto *input2 = kernel->input2();
+ const auto *output = kernel->output();
+
+ const auto input1_scale = static_cast<double>(Tensor::scale(input1));
+ const auto input2_scale = static_cast<double>(Tensor::scale(input2));
+ const auto output_scale = static_cast<double>(Tensor::scale(output));
+
+ const int left_shift = 20;
+ const double twice_max_input_scale = 2 * std::max(input1_scale, input2_scale);
+ const double real_input1_multiplier = input1_scale / twice_max_input_scale;
+ const double real_input2_multiplier = input2_scale / twice_max_input_scale;
+ const double real_output_multiplier = twice_max_input_scale / ((1 << left_shift) * output_scale);
+
+ int32_t input1_multiplier{}, input2_multiplier{}, output_multiplier{};
+ int input1_shift{}, input2_shift{}, output_shift{};
+ kernels::quantizeMultiplierSmallerThanOneExp(real_input1_multiplier, &input1_multiplier,
+ &input1_shift);
+ kernels::quantizeMultiplierSmallerThanOneExp(real_input2_multiplier, &input2_multiplier,
+ &input2_shift);
+ kernels::quantizeMultiplierSmallerThanOneExp(real_output_multiplier, &output_multiplier,
+ &output_shift);
+
+ int32_t activation_min{};
+ int32_t activation_max{};
+ kernels::calculateActivationRangeQuantized(luci_actfunc(options->fused_activation_function()),
+ output, &activation_min, &activation_max);
+
+ luci_interpreter_pal::ArithmeticParams params{};
+ params.left_shift = left_shift;
+ // The kernel expects inputs' zero points to be negated.
+ params.input1_offset = -Tensor::zero_point(input1); // Note the '-'.
+ params.input1_multiplier = input1_multiplier;
+ params.input1_shift = input1_shift;
+ params.input2_offset = -Tensor::zero_point(input2); // Note the '-'.
+ params.input2_multiplier = input2_multiplier;
+ params.input2_shift = input2_shift;
+ params.output_offset = Tensor::zero_point(output);
+ params.output_multiplier = output_multiplier;
+ params.output_shift = output_shift;
+ params.quantized_activation_min = activation_min;
+ params.quantized_activation_max = activation_max;
+
+ const bool need_broadcast = luci_interpreter_pal::ProcessBroadcastShapes(
+ kernels::getTensorShape(input1), kernels::getTensorShape(input2), &params);
+
+ if (need_broadcast)
+ {
+ tiso_broadcast_func(
+ params, kernels::getTensorShape(input1), kernels::getTensorData<T>(kernel_data->input1_data),
+ kernels::getTensorShape(input2), kernels::getTensorData<T>(kernel_data->input2_data),
+ kernels::getTensorShape(output), kernels::getTensorData<T>(kernel_data->output_data));
+ }
+ else
+ {
+ tiso_func(params, kernels::getTensorShape(input1),
+ kernels::getTensorData<uint8_t>(kernel_data->input1_data),
+ kernels::getTensorShape(input2), kernels::getTensorData<T>(kernel_data->input2_data),
+ kernels::getTensorShape(output), kernels::getTensorData<T>(kernel_data->output_data));
+ }
+}
+
+template <typename T, typename TISOFunc = nullptr_t, typename TISOBroadcastFunc = nullptr_t,
+ typename Options = nullptr_t>
+void evalTISOInplaceQuantizedKernel(TISOFunc tiso_func, TISOBroadcastFunc tiso_broadcast_func,
+ kernels::TISOKernel *kernel, const Options *options)
{
- if (unextended_input1_shape == unextended_input2_shape)
+ uint8_t *inplace_data_ptr = nullptr;
+ circle::Tensor *input_inplace_tensor = nullptr;
+
+ kernels::TISOData kernel_data = kernel->readInplaceData(inplace_data_ptr, input_inplace_tensor);
+
+ evalTISOQuantizedKernel<T, TISOFunc, TISOBroadcastFunc, Options>(tiso_func, tiso_broadcast_func,
+ kernel, &kernel_data, options);
+
+ kernel->runtime_graph()->makeInplaceOperation(input_inplace_tensor, kernel->output());
+ if (input_inplace_tensor == kernel->input1())
{
- const int flat_size = tflite::MatchingElementsSize(
- unextended_input1_shape, unextended_input2_shape, unextended_output_shape);
- for (int i = 0; i < flat_size; ++i)
- {
- output_data[i] = op(input1_data[i], input2_data[i]);
- }
+ kernel->runtime_graph()->makeInplaceOperation(kernel->input2(), nullptr);
}
else
{
- assert(unextended_input1_shape.DimensionsCount() <= N);
- assert(unextended_input2_shape.DimensionsCount() <= N);
- assert(unextended_output_shape.DimensionsCount() <= N);
-
- tflite::NdArrayDesc<N> desc1{};
- tflite::NdArrayDesc<N> desc2{};
- tflite::NdArrayDesc<N> output_desc{};
- tflite::NdArrayDescsForElementwiseBroadcast(unextended_input1_shape, unextended_input2_shape,
- &desc1, &desc2);
- tflite::CopyDimsToDesc(tflite::RuntimeShape::ExtendedShape(N, unextended_output_shape),
- &output_desc);
-
- auto fn = [&](int indexes[N]) {
- output_data[SubscriptToIndex(output_desc, indexes)] =
- op(input1_data[SubscriptToIndex(desc1, indexes)],
- input2_data[SubscriptToIndex(desc2, indexes)]);
- };
- tflite::NDOpsHelper<N>(output_desc, fn);
+ kernel->runtime_graph()->makeInplaceOperation(kernel->input1(), nullptr);
}
}
+#endif // DIS_QUANT
+
} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Builders.h b/onert-micro/luci-interpreter/src/kernels/Builders.h
index 13646a338..a49f71e6c 100644
--- a/onert-micro/luci-interpreter/src/kernels/Builders.h
+++ b/onert-micro/luci-interpreter/src/kernels/Builders.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,19 +17,26 @@
#ifndef LUCI_INTERPRETER_KERNELS_NODES_BUILDERS_H
#define LUCI_INTERPRETER_KERNELS_NODES_BUILDERS_H
-#include "KernelBuilder.h"
#include "luci_interpreter/core/reader/CircleMicroReader.h"
-#include "core/RuntimeGraph.h"
+#include "core/RuntimeModule.h"
namespace luci_interpreter
{
+namespace
+{
+#ifdef USE_STATIC_ALLOC
+using BaseRuntimeGraph = StaticRuntimeGraph;
+#else
+using BaseRuntimeGraph = RuntimeGraph;
+#endif // USE_STATIC_ALLOC
+} // namespace
+
#define REGISTER_KERNEL(builtin_operator, name) \
void configure_kernel_Circle##name(const circle::Operator *cur_op, \
BaseRuntimeGraph *runtime_graph); \
\
- void execute_kernel_Circle##name(const circle::Operator *cur_op, \
- BaseRuntimeGraph *runtime_graph, bool is_inplace);
+ void execute_kernel_Circle##name(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph);
#if USE_GENERATED_LIST
#include "GeneratedKernelsToBuild.lst"
diff --git a/onert-micro/luci-interpreter/src/kernels/CMakeLists.txt b/onert-micro/luci-interpreter/src/kernels/CMakeLists.txt
index f59aa9071..66c0a9e9d 100644
--- a/onert-micro/luci-interpreter/src/kernels/CMakeLists.txt
+++ b/onert-micro/luci-interpreter/src/kernels/CMakeLists.txt
@@ -1,11 +1,14 @@
set(SOURCES
BinaryOpCommon.h
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
Utils.h
Utils.cpp
Builders.h
KernelBuilder.h
- KernelBuilder.cpp)
+ KernelBuilder.cpp
+ SISOKernel.h
+ TISOKernel.h
+ MISOKernel.h
+ PadCommon.cpp)
macro(REGISTER_KERNEL OPERATOR, NODE)
list(APPEND SOURCES "${NODE}.cpp")
@@ -21,6 +24,7 @@ target_include_directories(${LUCI_INTERPRETER_KERNELS} PUBLIC ${LUCI_INTERPRETER
target_link_libraries(${LUCI_INTERPRETER_KERNELS} PUBLIC ${LUCI_INTERPRETER_CORE})
+target_include_directories(${LUCI_INTERPRETER_KERNELS} PUBLIC ${LUCI_INTERPRETER_PAL_COMMON_DIR})
add_pal_to_target(${LUCI_INTERPRETER_KERNELS})
if(NOT ENABLE_TEST)
@@ -38,4 +42,6 @@ include(${KERNEL_REGISTER_FILE})
list(APPEND TEST_SOURCES TestUtils.h TestUtils.cpp)
GTest_AddTest(${LUCI_INTERPRETER_KERNELS}_test ${TEST_SOURCES})
-target_link_libraries(${LUCI_INTERPRETER_KERNELS}_test ${LUCI_INTERPRETER_KERNELS})
+target_link_libraries(${LUCI_INTERPRETER_KERNELS}_test onert_micro_coverage)
+target_link_libraries(${LUCI_INTERPRETER_KERNELS} PUBLIC onert_micro_coverage)
+target_link_libraries(${LUCI_INTERPRETER_KERNELS}_test ${LUCI_INTERPRETER_LOADER})
diff --git a/onert-micro/luci-interpreter/src/kernels/Cast.h b/onert-micro/luci-interpreter/src/kernels/Cast.h
index 9249ccced..f0bd02037 100644
--- a/onert-micro/luci-interpreter/src/kernels/Cast.h
+++ b/onert-micro/luci-interpreter/src/kernels/Cast.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Cast.test.cpp b/onert-micro/luci-interpreter/src/kernels/Cast.test.cpp
index 6a463d29e..4713ad34c 100644
--- a/onert-micro/luci-interpreter/src/kernels/Cast.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Cast.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Concatenation.cpp b/onert-micro/luci-interpreter/src/kernels/Concatenation.cpp
index a9eff09d0..c8c096ef9 100644
--- a/onert-micro/luci-interpreter/src/kernels/Concatenation.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Concatenation.cpp
@@ -18,7 +18,7 @@
#include "Builders.h"
#include "kernels/Utils.h"
-#include <tensorflow/lite/kernels/internal/reference/concatenation.h>
+#include "PALConcatenation.h"
namespace luci_interpreter
{
@@ -27,7 +27,7 @@ namespace
{
template <typename T>
-void evalGeneric(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph, bool)
+void evalGeneric(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
const auto output_index = cur_op->outputs()->operator[](0);
@@ -44,37 +44,38 @@ void evalGeneric(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph
const auto input_sizes = cur_op->inputs()->size();
std::vector<const T *> all_input_data;
- std::vector<tflite::RuntimeShape> all_shape;
- std::vector<tflite::RuntimeShape *> all_shape_ptr;
-
- all_input_data.reserve(input_sizes);
- all_shape.reserve(input_sizes);
- all_shape_ptr.reserve(input_sizes);
+ std::vector<luci_interpreter::RuntimeShape> all_shape;
+ std::vector<luci_interpreter::RuntimeShape *> all_shape_ptr;
for (int32_t i = 0; i < input_sizes; ++i)
{
auto input_index = cur_op->inputs()->operator[](i);
const auto *tensor = runtime_graph->getCircleTensorByIndex(input_index);
- auto *data = reinterpret_cast<const T *>(runtime_graph->getDataByTensor(tensor));
+ const auto *tensor_data = runtime_graph->getDataByTensor(tensor);
+ if (tensor_data == nullptr)
+ tensor_data = runtime_graph->getConstDataByTensor(tensor);
+
+ auto *data = reinterpret_cast<const T *>(tensor_data);
+
+ auto runtime_shape = kernels::getTensorRuntimeShape(tensor, runtime_graph);
all_input_data.push_back(data);
- all_shape.push_back(kernels::getTensorShape(tensor));
+ all_shape.push_back(runtime_shape);
}
- for (tflite::RuntimeShape &shape : all_shape)
+ for (luci_interpreter::RuntimeShape &shape : all_shape)
{
all_shape_ptr.push_back(&shape);
}
auto *output_data = reinterpret_cast<T *>(runtime_graph->getDataByTensor(output));
- // kernels::VectorOfTensors<T, true> inputs(_inputs);
- tflite::ConcatenationParams params{};
+ luci_interpreter_pal::ConcatenationParams params{};
params.axis = axis;
- params.inputs_count = input_sizes;
- tflite::reference_ops::Concatenation(params, all_shape_ptr.data(), all_input_data.data(),
- kernels::getTensorShape(output), output_data);
+ params.inputs_count = all_shape.size();
+ luci_interpreter_pal::Concatenation(params, all_shape_ptr.data(), all_input_data.data(),
+ kernels::getTensorShape(output), output_data);
}
} // namespace
@@ -104,24 +105,12 @@ void configure_kernel_CircleConcatenation(const circle::Operator *cur_op,
axis += Tensor::num_dims(t0);
LUCI_INTERPRETER_CHECK(axis >= 0 && axis < Tensor::num_dims(t0));
- int32_t sum_axis = Tensor::dim(t0, axis);
for (int i = 1; i < num_inputs; ++i)
{
input_index = cur_op->inputs()->operator[](i);
const auto *tensor = runtime_graph->getCircleTensorByIndex(input_index);
LUCI_INTERPRETER_CHECK(Tensor::element_type(tensor) == Tensor::element_type(t0));
LUCI_INTERPRETER_CHECK(Tensor::num_dims(tensor) == Tensor::num_dims(t0));
- for (int d = 0; d < Tensor::num_dims(t0); ++d)
- {
- if (d == axis)
- {
- sum_axis += Tensor::dim(tensor, axis);
- }
- else
- {
- LUCI_INTERPRETER_CHECK(Tensor::dim(tensor, d) == Tensor::dim(t0, d));
- }
- }
}
#ifndef DIS_QUANT
@@ -145,7 +134,7 @@ void configure_kernel_CircleConcatenation(const circle::Operator *cur_op,
}
void execute_kernel_CircleConcatenation(const circle::Operator *cur_op,
- BaseRuntimeGraph *runtime_graph, bool is_inplace)
+ BaseRuntimeGraph *runtime_graph)
{
int num_inputs = cur_op->inputs()->size();
LUCI_INTERPRETER_CHECK(num_inputs > 0);
@@ -158,20 +147,20 @@ void execute_kernel_CircleConcatenation(const circle::Operator *cur_op,
{
#ifndef DIS_FLOAT
case DataType::FLOAT32:
- evalGeneric<float>(cur_op, runtime_graph, is_inplace);
+ evalGeneric<float>(cur_op, runtime_graph);
break;
#endif // DIS_FLOAT
#ifndef DIS_QUANT
case DataType::S8:
- evalGeneric<int8_t>(cur_op, runtime_graph, is_inplace);
+ evalGeneric<int8_t>(cur_op, runtime_graph);
break;
+#endif // DIS_QUANT
case DataType::S32:
- evalGeneric<int32_t>(cur_op, runtime_graph, is_inplace);
+ evalGeneric<int32_t>(cur_op, runtime_graph);
break;
case DataType::S64:
- evalGeneric<int64_t>(cur_op, runtime_graph, is_inplace);
+ evalGeneric<int64_t>(cur_op, runtime_graph);
break;
-#endif
default:
assert(false && "Unsupported type.");
}
diff --git a/onert-micro/luci-interpreter/src/kernels/Concatenation.test.cpp b/onert-micro/luci-interpreter/src/kernels/Concatenation.test.cpp
index 25234c5cf..6f00941c0 100644
--- a/onert-micro/luci-interpreter/src/kernels/Concatenation.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Concatenation.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,16 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-// TODO enable it
-#if 0
-#include "kernels/Concatenation.h"
+
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/concatenation/FloatConcatenationKernel.h"
+#include "luci_interpreter/test_models/concatenation/IntConcatenationKernel.h"
+#include "luci_interpreter/test_models/concatenation/NegConcatenationKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
@@ -31,241 +30,106 @@ using namespace testing;
class ConcatenationTest : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-TEST_F(ConcatenationTest, Float)
+template <typename T>
+std::vector<T> checkConcatenationKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- std::vector<float> input1_data{1, 2, 3, 4, 5, 6};
- std::vector<float> input2_data{7, 8, 9, 10, 11, 12};
- Tensor input1_tensor =
- makeInputTensor<DataType::FLOAT32>({2, 3}, input1_data, _memory_manager.get());
- Tensor input2_tensor =
- makeInputTensor<DataType::FLOAT32>({2, 3}, input2_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
- ConcatenationParams params{};
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- // Try different 'axis' and expect different results.
- {
- params.axis = 0;
- params.activation = luci::FusedActFunc::NONE;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
- kernel.configure();
- for (auto t : kernel.getOutputTensors())
- {
- _memory_manager->allocate_memory(*t);
- }
- kernel.execute();
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 2);
- EXPECT_THAT(extractTensorData<float>(output_tensor),
- FloatArrayNear({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}));
- }
+ // set left input data
{
- params.axis = -2; // Same as '0'.
- params.activation = luci::FusedActFunc::NONE;
-
- Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<float>(output_tensor),
- FloatArrayNear({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}));
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
}
- {
- params.axis = 1;
- params.activation = luci::FusedActFunc::NONE;
-
- Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
- EXPECT_THAT(extractTensorData<float>(output_tensor),
- FloatArrayNear({1, 2, 3, 7, 8, 9, 4, 5, 6, 10, 11, 12}));
- }
+ // set right input data
{
- params.axis = -1; // Same as '1'.
- params.activation = luci::FusedActFunc::NONE;
-
- Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<float>(output_tensor),
- FloatArrayNear({1, 2, 3, 7, 8, 9, 4, 5, 6, 10, 11, 12}));
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(1));
+ std::copy(test_data_base->get_input_data_by_index(1).begin(),
+ test_data_base->get_input_data_by_index(1).end(), input_tensor_data);
}
-}
-TEST_F(ConcatenationTest, Input_Number_Check_NEG)
-{
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
- ConcatenationParams params{};
+ runtime_module.execute();
- params.axis = -1;
- params.activation = luci::FusedActFunc::NONE;
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
- Concatenation kernel({}, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST_F(ConcatenationTest, Invalid_Axis_NEG)
+TEST_F(ConcatenationTest, Float_P)
{
- std::vector<float> input1_data{1, 2, 3, 4, 5, 6};
- std::vector<float> input2_data{7, 8, 9, 10, 11, 12};
- Tensor input1_tensor =
- makeInputTensor<DataType::FLOAT32>({2, 3}, input1_data, _memory_manager.get());
- Tensor input2_tensor =
- makeInputTensor<DataType::FLOAT32>({2, 3}, input2_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
- ConcatenationParams params{};
-
- params.axis = -3;
- params.activation = luci::FusedActFunc::NONE;
-
- Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::TestDataFloatConcatenation test_data_kernel;
+ std::vector<float> output_data_vector = checkConcatenationKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+ test_data_kernel.get_output_data_by_index(0), 0.0001f));
}
-TEST_F(ConcatenationTest, Mismatching_Input_Type_NEG)
+TEST_F(ConcatenationTest, Int32_P)
{
- std::vector<float> input1_data{1, 2, 3, 4, 5, 6};
- std::vector<uint8_t> input2_data{7, 8, 9, 10, 11, 12};
- Tensor input1_tensor =
- makeInputTensor<DataType::FLOAT32>({2, 3}, input1_data, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::U8>({2, 3}, input2_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
- ConcatenationParams params{};
-
- params.axis = -1;
- params.activation = luci::FusedActFunc::NONE;
-
- Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::TestDataS32Concatenation test_data_kernel;
+ std::vector<int32_t> output_data_vector = checkConcatenationKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-TEST_F(ConcatenationTest, Mismatching_Input_Dimension_Num_NEG)
+TEST_F(ConcatenationTest, Int64_P)
{
- std::vector<float> input1_data{1, 2, 3, 4, 5, 6};
- std::vector<float> input2_data{7, 8, 9, 10, 11, 12};
- Tensor input1_tensor =
- makeInputTensor<DataType::FLOAT32>({2, 3}, input1_data, _memory_manager.get());
- Tensor input2_tensor =
- makeInputTensor<DataType::FLOAT32>({1, 2, 3}, input2_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
- ConcatenationParams params{};
-
- params.axis = -1;
- params.activation = luci::FusedActFunc::NONE;
-
- Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::TestDataS64Concatenation test_data_kernel;
+ std::vector<int64_t> output_data_vector = checkConcatenationKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-TEST_F(ConcatenationTest, Mismatching_Input_Dimension_NEG)
+TEST_F(ConcatenationTest, InputTypeMismatch_NEG)
{
- std::vector<float> input1_data{1, 2, 3, 4, 5, 6};
- std::vector<float> input2_data{7, 8, 9, 10, 11, 12, 13, 14, 15};
- Tensor input1_tensor =
- makeInputTensor<DataType::FLOAT32>({2, 3}, input1_data, _memory_manager.get());
- Tensor input2_tensor =
- makeInputTensor<DataType::FLOAT32>({3, 3}, input2_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
- ConcatenationParams params{};
-
- params.axis = -1;
- params.activation = luci::FusedActFunc::NONE;
-
- Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::TestDataInputTypeMismatchConcatenation test_data_kernel;
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST_F(ConcatenationTest, Int8_Mismatching_Input_Type_NEG)
+TEST_F(ConcatenationTest, InputOutputTypeMismatch_NEG)
{
- std::vector<uint8_t> input1_data{1, 2, 3, 4};
- std::vector<int8_t> input2_data{5, 6, 7, 8};
- Tensor input1_tensor = makeInputTensor<DataType::U8>({2, 2}, input1_data, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::S8>({2, 2}, input2_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S8);
- ConcatenationParams params{};
-
- params.axis = -1;
- params.activation = luci::FusedActFunc::NONE;
-
- Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::TestDataReluConcatenation test_data_kernel;
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST_F(ConcatenationTest, Int8_Mismatching_Input_Output_Quant_Params_NEG)
+TEST_F(ConcatenationTest, WrongAxis_NEG)
{
- std::vector<float> input1_data{1, 2, 3, 4, 5, 6};
- std::vector<float> input2_data{7, 8, 9, 10, 11, 12};
- int quantized_dimension = 3;
- std::vector<float> scales{0.1, 0.2, 0.3};
- std::vector<int32_t> zero_points{1, -1, 1};
-
- Tensor input1_tensor = makeInputTensor<DataType::S8>(
- {1, 1, 2, 3}, scales, zero_points, quantized_dimension, input1_data, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::S8>(
- {1, 1, 2, 3}, scales, zero_points, quantized_dimension, input2_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S8, scales.at(0), zero_points.at(0));
- ConcatenationParams params{};
-
- params.axis = -1;
- params.activation = luci::FusedActFunc::NONE;
-
- Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::TestDataWrongAxisConcatenation test_data_kernel;
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST_F(ConcatenationTest, Int8_Mismatching_Zero_Point_NEG)
-{
- std::vector<float> input1_data{1, 2, 3, 4};
- std::vector<float> input2_data{5, 6, 7, 8};
- float scale = 0.1;
- int32_t zero_point_1 = 1;
- int32_t zero_point_2 = -1;
-
- Tensor input1_tensor =
- makeInputTensor<DataType::S8>({2, 2}, scale, zero_point_1, input1_data, _memory_manager.get());
- Tensor input2_tensor =
- makeInputTensor<DataType::S8>({2, 2}, scale, zero_point_2, input2_data, _memory_manager.get());
-
- Tensor output_tensor = makeOutputTensor(DataType::S8, scale, zero_point_1);
- ConcatenationParams params{};
-
- params.axis = -1;
- params.activation = luci::FusedActFunc::NONE;
-
- Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
-}
-
-// TODO: Remove this test when concat w/ fused_activation is supported
-TEST_F(ConcatenationTest, With_Fused_Activation_NEG)
-{
- std::vector<float> input1_data{1, 2, 3, 4, 5, 6};
- std::vector<float> input2_data{7, 8, 9, 10, 11, 12};
- Tensor input1_tensor =
- makeInputTensor<DataType::FLOAT32>({2, 3}, input1_data, _memory_manager.get());
- Tensor input2_tensor =
- makeInputTensor<DataType::FLOAT32>({2, 3}, input2_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
- ConcatenationParams params{};
-
- params.axis = 1;
- params.activation = luci::FusedActFunc::RELU;
-
- Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
-}
+// TODO: add tests for S8
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
-#endif
diff --git a/onert-micro/luci-interpreter/src/kernels/Conv2D.cpp b/onert-micro/luci-interpreter/src/kernels/Conv2D.cpp
index 704524935..75bccbcb8 100644
--- a/onert-micro/luci-interpreter/src/kernels/Conv2D.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Conv2D.cpp
@@ -66,7 +66,7 @@ void evalFloat(const circle::Tensor *input, const circle::Tensor *filter,
kernels::calculateActivationRange(luci_actfunc(options->fused_activation_function()),
&activation_min, &activation_max);
- tflite::ConvParams params{};
+ luci_interpreter_pal::ConvParams params{};
params.padding_values.height = compute_padding_h(input, filter, options);
params.padding_values.width = compute_padding_w(input, filter, options);
params.stride_height = options->stride_h();
@@ -82,12 +82,19 @@ void evalFloat(const circle::Tensor *input, const circle::Tensor *filter,
auto *filter_data = runtime_graph->getConstDataByTensor(filter);
auto *bias_data = runtime_graph->getConstDataByTensor(bias);
- luci_interpreter_pal::Conv(
- params, kernels::getTensorShape(input), kernels::getTensorData<float>(input_data),
- kernels::getTensorShape(filter), kernels::getTensorData<float>(filter_data),
- kernels::getTensorShape(bias), kernels::getTensorData<float>(bias_data),
- kernels::getTensorShape(output), kernels::getTensorData<float>(output_data),
- kernels::getTensorShape(nullptr), nullptr);
+ int32_t input_shape[kMaxSmallSize];
+ kernels::getTensorDims(input, runtime_graph, input_shape);
+
+ int32_t filter_shape[kMaxSmallSize];
+ kernels::getTensorDims(filter, runtime_graph, filter_shape);
+
+ int32_t output_shape[kMaxSmallSize];
+ kernels::getTensorDims(output, runtime_graph, output_shape);
+
+ luci_interpreter_pal::Conv(params, input_shape, kernels::getTensorData<float>(input_data),
+ filter_shape, kernels::getTensorData<float>(filter_data),
+ kernels::getTensorData<float>(bias_data), output_shape,
+ kernels::getTensorData<float>(output_data));
}
#endif // DIS_FLOAT
@@ -112,7 +119,7 @@ void evalQuantized(const circle::Tensor *input, const circle::Tensor *filter,
kernels::calculateActivationRangeQuantized(luci_actfunc(options->fused_activation_function()),
output, &activation_min, &activation_max);
- tflite::ConvParams params{};
+ luci_interpreter_pal::ConvParams params{};
params.padding_values.height = compute_padding_h(input, filter, options);
params.padding_values.width = compute_padding_w(input, filter, options);
params.stride_height = options->stride_h();
@@ -134,12 +141,19 @@ void evalQuantized(const circle::Tensor *input, const circle::Tensor *filter,
auto *filter_data = runtime_graph->getConstDataByTensor(filter);
auto *bias_data = runtime_graph->getConstDataByTensor(bias);
- luci_interpreter_pal::Conv(
- params, kernels::getTensorShape(input), kernels::getTensorData<uint8_t>(input_data),
- kernels::getTensorShape(filter), kernels::getTensorData<uint8_t>(filter_data),
- kernels::getTensorShape(bias), kernels::getTensorData<int32_t>(bias_data),
- kernels::getTensorShape(output), kernels::getTensorData<uint8_t>(output_data),
- kernels::getTensorShape(nullptr), nullptr);
+ int32_t input_shape[kMaxSmallSize];
+ kernels::getTensorDims(input, runtime_graph, input_shape);
+
+ int32_t filter_shape[kMaxSmallSize];
+ kernels::getTensorDims(filter, runtime_graph, filter_shape);
+
+ int32_t output_shape[kMaxSmallSize];
+ kernels::getTensorDims(output, runtime_graph, output_shape);
+
+ luci_interpreter_pal::Conv(params, input_shape, kernels::getTensorData<uint8_t>(input_data),
+ filter_shape, kernels::getTensorData<uint8_t>(filter_data),
+ kernels::getTensorData<int32_t>(bias_data), output_shape,
+ kernels::getTensorData<uint8_t>(output_data));
}
void evalQuantizedPerChannel(const circle::Tensor *input, const circle::Tensor *filter,
@@ -223,7 +237,7 @@ void evalQuantizedPerChannel(const circle::Tensor *input, const circle::Tensor *
acc += bias_data[out_c];
}
- int32_t scaled_acc = tflite::MultiplyByQuantizedMultiplier(
+ int32_t scaled_acc = luci_interpreter_pal::multiplyByQuantizedMultiplier(
acc, quant_multipliers[out_c].multiplier, quant_multipliers[out_c].shift);
scaled_acc += Tensor::zero_point(output);
@@ -235,150 +249,6 @@ void evalQuantizedPerChannel(const circle::Tensor *input, const circle::Tensor *
}
}
}
-
-void evalQuantizedS8PerChannel(const circle::Tensor *input, const circle::Tensor *filter,
- const circle::Tensor *bias, const circle::Tensor *output,
- const circle::Conv2DOptions *options,
- BaseRuntimeGraph *runtime_graph)
-{
- int32_t activation_min{};
- int32_t activation_max{};
- kernels::calculateActivationRangeQuantized(luci_actfunc(options->fused_activation_function()),
- output, &activation_min, &activation_max);
-
- tflite::ConvParams params{};
- params.padding_values.height = compute_padding_h(input, filter, options);
- params.padding_values.width = compute_padding_w(input, filter, options);
- params.stride_height = options->stride_h();
- params.stride_width = options->stride_w();
- params.dilation_height_factor = options->dilation_h_factor();
- params.dilation_width_factor = options->dilation_w_factor();
- // The kernel expects filter zero points to be negated.
- params.input_offset = -Tensor::zero_point(input); // Note the '-'.
- params.weights_offset = 0; // Unused in tflite code
- params.output_offset = Tensor::zero_point(output);
- params.quantized_activation_min = activation_min;
- params.quantized_activation_max = activation_max;
-
- const std::vector<double> effective_output_scales = kernels::getQuantizedConvolutionMultiplers(
- Tensor::scale(input), Tensor::scales(filter), Tensor::scale(output));
-
- std::vector<kernels::ChannelQuantMultipliers> quant_multipliers =
- kernels::quantizeMultipliers(effective_output_scales);
-
- std::vector<int32_t> shifts;
- std::transform(quant_multipliers.begin(), quant_multipliers.end(), std::back_inserter(shifts),
- [](kernels::ChannelQuantMultipliers cm) { return cm.shift; });
- std::vector<int32_t> multipliers;
- std::transform(quant_multipliers.begin(), quant_multipliers.end(),
- std::back_inserter(multipliers),
- [](kernels::ChannelQuantMultipliers cm) { return cm.multiplier; });
-
- auto *input_data = runtime_graph->getDataByTensor(input);
- auto *output_data = runtime_graph->getDataByTensor(output);
-
- auto *filter_data = runtime_graph->getConstDataByTensor(filter);
- auto *bias_data = runtime_graph->getConstDataByTensor(bias);
-
- luci_interpreter_pal::ConvPerChannel(
- params, multipliers.data(), shifts.data(), kernels::getTensorShape(input),
- kernels::getTensorData<int8_t>(input_data), kernels::getTensorShape(filter),
- kernels::getTensorData<int8_t>(filter_data), kernels::getTensorShape(bias),
- kernels::getTensorData<int32_t>(bias_data), kernels::getTensorShape(output),
- kernels::getTensorData<int8_t>(output_data), kernels::getTensorShape(nullptr), nullptr);
-}
-
-void evalQuantizedS16(const circle::Tensor *input, const circle::Tensor *filter,
- const circle::Tensor *bias, const circle::Tensor *output,
- const circle::Conv2DOptions *options, BaseRuntimeGraph *runtime_graph)
-{
- auto *raw_input_data = runtime_graph->getDataByTensor(input);
- auto *raw_output_data = runtime_graph->getDataByTensor(output);
-
- auto *raw_filter_data = runtime_graph->getConstDataByTensor(filter);
- auto *raw_bias_data = runtime_graph->getConstDataByTensor(bias);
-
- const auto *input_data = kernels::getTensorData<uint8_t>(raw_input_data);
- const auto *filter_data = kernels::getTensorData<uint8_t>(raw_filter_data);
- const auto *bias_data = kernels::getTensorData<int32_t>(raw_bias_data);
- auto *output_data = kernels::getTensorData<uint8_t>(raw_output_data);
-
- const int32_t batches = Tensor::dim(input, 0);
- const int32_t input_height = Tensor::dim(input, 1);
- const int32_t input_width = Tensor::dim(input, 2);
- const int32_t input_depth = Tensor::dim(input, 3);
- const int32_t output_depth = Tensor::dim(filter, 0);
- const int32_t filter_height = Tensor::dim(filter, 1);
- const int32_t filter_width = Tensor::dim(filter, 2);
- const int32_t output_height = Tensor::dim(output, 1);
- const int32_t output_width = Tensor::dim(output, 2);
-
- const int32_t stride_height = options->stride_h();
- const int32_t stride_width = options->stride_w();
- const int32_t dilation_height_factor = options->dilation_h_factor();
- const int32_t dilation_width_factor = options->dilation_w_factor();
-
- int32_t activation_min{};
- int32_t activation_max{};
- kernels::calculateActivationRangeQuantized(luci_actfunc(options->fused_activation_function()),
- output, &activation_min, &activation_max);
-
- const std::vector<double> effective_output_scale = kernels::getQuantizedConvolutionMultiplers(
- Tensor::scale(input), Tensor::scales(filter), Tensor::scale(output));
-
- const std::vector<kernels::ChannelQuantMultipliers> multipliers_raw =
- kernels::quantizeMultipliers(effective_output_scale);
- kernels::BroadcastableWrapper<kernels::ChannelQuantMultipliers> multipliers(multipliers_raw);
-
- for (int32_t batch = 0; batch < batches; ++batch)
- {
- for (int32_t out_y = 0; out_y < output_height; ++out_y)
- {
- for (int32_t out_x = 0; out_x < output_width; ++out_x)
- {
- for (int32_t out_c = 0; out_c < output_depth; ++out_c)
- {
- const int32_t in_y_origin =
- out_y * stride_height - compute_padding_h(input, filter, options);
- const int32_t in_x_origin =
- out_x * stride_width - compute_padding_w(input, filter, options);
- int64_t acc = 0;
- for (int32_t filter_y = 0; filter_y < filter_height; ++filter_y)
- {
- for (int32_t filter_x = 0; filter_x < filter_width; ++filter_x)
- {
- const int32_t in_y = in_y_origin + dilation_height_factor * filter_y;
- const int32_t in_x = in_x_origin + dilation_width_factor * filter_x;
- if ((in_y >= 0 && in_y < input_height) && (in_x >= 0 && in_x < input_width))
- {
- for (int32_t in_c = 0; in_c < input_depth; ++in_c)
- {
- const int16_t input_val =
- input_data[kernels::calcOffset(input, batch, in_y, in_x, in_c)];
- const int16_t filter_val =
- filter_data[kernels::calcOffset(filter, out_c, filter_y, filter_x, in_c)];
- acc += static_cast<int64_t>(input_val) * static_cast<int64_t>(filter_val);
- }
- }
- }
- }
- if (bias_data)
- {
- acc += bias_data[out_c];
- }
-
- int32_t scaled_acc = tflite::MultiplyByQuantizedMultiplier(
- acc, multipliers[out_c].multiplier, multipliers[out_c].shift);
-
- scaled_acc = std::max(scaled_acc, activation_min);
- scaled_acc = std::min(scaled_acc, activation_max);
-
- output_data[kernels::calcOffset(output, batch, out_y, out_x, out_c)] = scaled_acc;
- }
- }
- }
- }
-}
#endif // DIS_QUANT
} // namespace
@@ -462,8 +332,7 @@ void configure_kernel_CircleConv2D(const circle::Operator *cur_op, BaseRuntimeGr
}
}
-void execute_kernel_CircleConv2D(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph,
- bool)
+void execute_kernel_CircleConv2D(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
const auto input_index = cur_op->inputs()->operator[](0);
const auto weight_index = cur_op->inputs()->operator[](1);
@@ -509,12 +378,6 @@ void execute_kernel_CircleConv2D(const circle::Operator *cur_op, BaseRuntimeGrap
evalQuantizedPerChannel(input, weights, bias, output, options, runtime_graph);
}
break;
- case DataType::S8:
- evalQuantizedS8PerChannel(input, weights, bias, output, options, runtime_graph);
- break;
- case DataType::S16:
- evalQuantizedS16(input, weights, bias, output, options, runtime_graph);
- break;
#endif // DIS_QUANT
default:
assert(false && "Unsupported type.");
diff --git a/onert-micro/luci-interpreter/src/kernels/Conv2D.test.cpp b/onert-micro/luci-interpreter/src/kernels/Conv2D.test.cpp
index 6c6d86077..c373bd28f 100644
--- a/onert-micro/luci-interpreter/src/kernels/Conv2D.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Conv2D.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,16 +14,15 @@
* limitations under the License.
*/
-// TODO enable it
-#if 0
-#include "kernels/Conv2D.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/conv2d/FloatConv2DKernel.h"
+#include "luci_interpreter/test_models/conv2d/U8Conv2DKernel.h"
+#include "luci_interpreter/test_models/conv2d/NegConv2DKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
@@ -32,680 +30,92 @@ using namespace testing;
class Conv2DTest : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-TEST_F(Conv2DTest, Float)
-{
- Shape input_shape{1, 4, 3, 2};
- Shape filter_shape{2, 2, 2, 2};
- Shape bias_shape{2};
- std::vector<float> input_data{
- 1, 2, 3, 4, 5, 6, // row = 0
- 7, 8, 9, 10, 11, 12, // row = 1
- 13, 14, 15, 16, 17, 18, // row = 2
- 19, 20, 21, 22, 23, 24, // row = 3
- };
- std::vector<float> filter_data{
- 1, 2, -3, -4, // out = 0, row = 0
- -5, 6, -7, 8, // out = 1, row = 0
- 4, -2, 3, -1, // out = 0, row = 1
- -8, -6, 7, 5, // out = 1, row = 1
- };
- std::vector<float> bias_data{1, 2};
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
- Tensor filter_tensor =
- makeInputTensor<DataType::FLOAT32>(filter_shape, filter_data, _memory_manager.get());
- Tensor bias_tensor =
- makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data, _memory_manager.get());
- Tensor im2col(DataType::FLOAT32, Shape({}), {}, "");
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- Conv2DParams params{};
- params.padding = Padding::VALID;
- params.stride_height = 2;
- params.stride_width = 1;
- params.dilation_height_factor = 1;
- params.dilation_width_factor = 1;
- params.activation = Activation::RELU;
-
- Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
- kernel.configure();
- _memory_manager->allocate_memory(im2col);
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- std::vector<float> ref_output_data{
- 11, 16, 7, 20, // row = 0
- 0, 40, 0, 44, // row = 1
- };
- std::vector<int32_t> ref_output_shape{1, 2, 2, 2};
- EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
-}
-
-TEST_F(Conv2DTest, FloatPointwise)
-{
- Shape input_shape{1, 2, 2, 2};
- Shape filter_shape{2, 1, 1, 2};
- Shape bias_shape{2};
- std::vector<float> input_data{
- 1, 2, // row = 0, col = 0
- 3, 4, // row = 0, col = 1
- 5, 6, // row = 1, col = 0
- 7, 8, // row = 1, col = 1
- };
- std::vector<float> filter_data{
- -1, 2, // out = 0
- -3, 4, // out = 1
- };
- std::vector<float> bias_data{1, 2};
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
- Tensor filter_tensor =
- makeInputTensor<DataType::FLOAT32>(filter_shape, filter_data, _memory_manager.get());
- Tensor bias_tensor =
- makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
- Tensor im2col(DataType::FLOAT32, Shape({}), {}, "");
-
- Conv2DParams params{};
- params.padding = Padding::VALID;
- params.stride_height = 1;
- params.stride_width = 1;
- params.dilation_height_factor = 1;
- params.dilation_width_factor = 1;
- params.activation = Activation::RELU;
-
- Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
- kernel.configure();
- _memory_manager->allocate_memory(im2col);
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- std::vector<float> ref_output_data{
- 4, 7, 6, 9, // row = 0
- 8, 11, 10, 13, // row = 1
- };
- std::vector<int32_t> ref_output_shape{1, 2, 2, 2};
- EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
-}
-
-TEST_F(Conv2DTest, FloatCheck)
-{
- Shape input_shape{2, 2, 4, 1};
- Shape filter_shape{3, 2, 2, 1};
- Shape bias_shape{3};
- std::vector<float> input_data{
- // First batch
- 1, 1, 1, 1, // row = 1
- 2, 2, 2, 2, // row = 2
- // Second batch
- 1, 2, 3, 4, // row = 1
- 1, 2, 3, 4, // row = 2
- };
- std::vector<float> filter_data{
- 1, 2, 3, 4, // first 2x2 filter
- -1, 1, -1, 1, // second 2x2 filter
- -1, -1, 1, 1, // third 2x2 filter
- };
- std::vector<float> bias_data{1, 2, 3};
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
- Tensor filter_tensor =
- makeInputTensor<DataType::FLOAT32>(filter_shape, filter_data, _memory_manager.get());
- Tensor bias_tensor =
- makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data, _memory_manager.get());
- Tensor im2col(DataType::FLOAT32, Shape({}), {}, "");
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- Conv2DParams params{};
- params.padding = Padding::VALID;
- params.stride_height = 2;
- params.stride_width = 2;
- params.dilation_height_factor = 1;
- params.dilation_width_factor = 1;
- params.activation = Activation::NONE;
-
- Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- _memory_manager->allocate_memory(im2col);
- kernel.execute();
-
- std::vector<float> ref_output_data{
- 18, 2, 5, // first batch, left
- 18, 2, 5, // first batch, right
- 17, 4, 3, // second batch, left
- 37, 4, 3, // second batch, right
- };
- std::vector<int32_t> ref_output_shape{2, 1, 2, 3};
- EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
-}
-
-TEST_F(Conv2DTest, Uint8)
-{
- std::vector<float> input_data{
- // First batch
- 1, 1, 1, 1, // row = 1
- 2, 2, 2, 2, // row = 2
- // Second batch
- 1, 2, 3, 4, // row = 1
- 1, 2, 3, 4, // row = 2
- };
- std::vector<float> filter_data{
- 1, 2, 3, 4, // first 2x2 filter
- -1, 1, -1, 1, // second 2x2 filter
- -1, -1, 1, 1, // third 2x2 filter
- };
- std::vector<float> bias_data{1, 2, 3};
-
- std::pair<float, int32_t> input_quant_param = quantizationParams<uint8_t>(-63.5, 64);
- std::pair<float, int32_t> output_quant_param = quantizationParams<uint8_t>(-127, 128);
-
- Tensor input_tensor =
- makeInputTensor<DataType::U8>({2, 2, 4, 1}, input_quant_param.first, input_quant_param.second,
- input_data, _memory_manager.get());
- Tensor filter_tensor =
- makeInputTensor<DataType::U8>({3, 2, 2, 1}, input_quant_param.first, input_quant_param.second,
- filter_data, _memory_manager.get());
- Tensor bias_tensor = makeInputTensor<DataType::S32>(
- {3}, input_quant_param.first * input_quant_param.first, 0, bias_data, _memory_manager.get());
- Tensor im2col(DataType::U8, Shape({}), {}, "");
- Tensor output_tensor =
- makeOutputTensor(DataType::U8, output_quant_param.first, output_quant_param.second);
-
- Conv2DParams params{};
- params.padding = Padding::VALID;
- params.stride_height = 2;
- params.stride_width = 2;
- params.dilation_height_factor = 1;
- params.dilation_width_factor = 1;
- params.activation = Activation::NONE;
-
- Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- _memory_manager->allocate_memory(im2col);
- kernel.execute();
-
- std::vector<float> ref_output_data{
- 18, 2, 5, // first batch, left
- 18, 2, 5, // first batch, right
- 17, 4, 3, // second batch, left
- 37, 4, 3, // second batch, right
- };
- std::vector<int32_t> ref_output_shape{2, 1, 2, 3};
- EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
-}
-
-TEST_F(Conv2DTest, Uint8_CWQ)
-{
- const int output_channels = 3;
- std::vector<float> input_data{
- // First batch
- 1, 1, 1, 1, // row = 1
- 2, 2, 2, 2, // row = 2
- // Second batch
- 1, 2, 3, 4, // row = 1
- 1, 2, 3, 4, // row = 2
- };
- std::vector<float> filter_data{
- 1, 2, 3, 4, // first 2x2 filter
- -1, 1, -1, 1, // second 2x2 filter
- -1, -1, 1, 1, // third 2x2 filter
- };
- std::vector<float> bias_data{1, 2, 3};
- Shape filter_shape{output_channels, 2, 2, 1};
-
- std::pair<float, int32_t> input_quant_param = quantizationParams<uint8_t>(0, 4);
- std::pair<float, int32_t> output_quant_param = quantizationParams<uint8_t>(-127, 128);
-
- std::vector<std::pair<float, int32_t>> filter_quant_params;
- filter_quant_params.push_back(quantizationParams<uint8_t>(0, 4));
- filter_quant_params.push_back(quantizationParams<uint8_t>(-1, 1));
- filter_quant_params.push_back(quantizationParams<uint8_t>(-1, 1));
-
- std::vector<float> filter_scales;
- std::vector<int32_t> filter_zerops;
- for (auto iter : filter_quant_params)
- {
- filter_scales.push_back(iter.first);
- filter_zerops.push_back(iter.second);
- }
-
- std::vector<float> bias_scales;
- for (int i = 0; i < output_channels; ++i)
- bias_scales.push_back(filter_quant_params[i].first * input_quant_param.first);
- std::vector<int32_t> zerop(output_channels, 0);
-
- Tensor input_tensor =
- makeInputTensor<DataType::U8>({2, 2, 4, 1}, input_quant_param.first, input_quant_param.second,
- input_data, _memory_manager.get());
- Tensor filter_tensor = makeInputTensor<DataType::U8>(filter_shape, filter_scales, filter_zerops,
- 0, filter_data, _memory_manager.get());
- Tensor bias_tensor = makeInputTensor<DataType::S32>({output_channels}, bias_scales, zerop, 0,
- bias_data, _memory_manager.get());
- Tensor im2col(DataType::U8, Shape({}), {}, "");
- Tensor output_tensor =
- makeOutputTensor(DataType::U8, output_quant_param.first, output_quant_param.second);
-
- Conv2DParams params{};
- params.padding = Padding::VALID;
- params.stride_height = 2;
- params.stride_width = 2;
- params.dilation_height_factor = 1;
- params.dilation_width_factor = 1;
- params.activation = Activation::NONE;
-
- Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- _memory_manager->allocate_memory(im2col);
- kernel.execute();
-
- std::vector<float> ref_output_data{
- 18, 2, 5, // first batch, left
- 18, 2, 5, // first batch, right
- 17, 4, 3, // second batch, left
- 37, 4, 3, // second batch, right
- };
- std::vector<int32_t> ref_output_shape{2, 1, 2, 3};
- EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
-}
-
-TEST_F(Conv2DTest, SInt8_CWQ)
+template <typename T> std::vector<T> checkConv2DKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- const int output_channels = 3;
- std::vector<float> input_data{
- // First batch
- 1, 1, 1, 1, // row = 1
- 2, 2, 2, 2, // row = 2
- // Second batch
- 1, 2, 3, 4, // row = 1
- 1, 2, 3, 4, // row = 2
- };
- std::vector<float> filter_data{
- 1, 2, 3, 4, // first 2x2 filter
- -1, 1, -1, 1, // second 2x2 filter
- -1, -1, 1, 1, // third 2x2 filter
- };
- std::vector<float> bias_data{1, 2, 3};
- Shape filter_shape{output_channels, 2, 2, 1};
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- std::pair<float, int32_t> input_quant_param = quantizationParams<int8_t>(0, 4);
- std::pair<float, int32_t> output_quant_param = quantizationParams<int8_t>(-127, 128);
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- std::vector<std::pair<float, int32_t>> filter_quant_params;
- filter_quant_params.push_back(std::pair<float, int32_t>(0.5, 0));
- filter_quant_params.push_back(std::pair<float, int32_t>(0.25, 0));
- filter_quant_params.push_back(std::pair<float, int32_t>(0.125, 0));
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
- std::vector<float> filter_scales;
- std::vector<int32_t> filter_zerops;
- for (auto iter : filter_quant_params)
+ // set input data
{
- filter_scales.push_back(iter.first);
- filter_zerops.push_back(iter.second);
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
}
- std::vector<float> bias_scales;
- for (int i = 0; i < output_channels; ++i)
- bias_scales.push_back(filter_quant_params[i].first * input_quant_param.first);
- std::vector<int32_t> zerop(output_channels, 0);
-
- Tensor input_tensor =
- makeInputTensor<DataType::S8>({2, 2, 4, 1}, input_quant_param.first, input_quant_param.second,
- input_data, _memory_manager.get());
- Tensor filter_tensor = makeInputTensor<DataType::S8>(filter_shape, filter_scales, filter_zerops,
- 0, filter_data, _memory_manager.get());
- Tensor bias_tensor = makeInputTensor<DataType::S32>({output_channels}, bias_scales, zerop, 0,
- bias_data, _memory_manager.get());
- Tensor im2col(DataType::S8, Shape({}), {}, "");
- Tensor output_tensor =
- makeOutputTensor(DataType::S8, output_quant_param.first, output_quant_param.second);
-
- Conv2DParams params{};
- params.padding = Padding::VALID;
- params.stride_height = 2;
- params.stride_width = 2;
- params.dilation_height_factor = 1;
- params.dilation_width_factor = 1;
- params.activation = Activation::NONE;
-
- Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- _memory_manager->allocate_memory(im2col);
- kernel.execute();
-
- std::vector<float> ref_output_data{
- 18, 2, 5, // first batch, left
- 18, 2, 5, // first batch, right
- 17, 4, 3, // second batch, left
- 37, 4, 3, // second batch, right
- };
- std::vector<int32_t> ref_output_shape{2, 1, 2, 3};
- EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
-}
-
-TEST_F(Conv2DTest, SInt16)
-{
- Shape input_shape{1, 4, 3, 2};
- Shape filter_shape{2, 2, 2, 2};
- Shape bias_shape{2};
- std::vector<int32_t> ref_output_shape{1, 2, 2, 2};
-
- std::vector<float> input_data{
- 1, 2, 3, 4, 5, 6, // row = 0
- 7, 8, 9, 10, 11, 12, // row = 1
- 13, 14, 15, 16, 17, 18, // row = 2
- 19, 20, 21, 22, 23, 24, // row = 3
- };
- std::vector<float> filter_data{
- 1, 2, -3, -4, // out = 0, row = 0
- -5, 6, -7, 8, // out = 1, row = 0
- 4, -2, 3, -1, // out = 0, row = 1
- -8, -6, 7, 5, // out = 1, row = 1
- };
- std::vector<float> bias_data{1, 2};
- std::vector<float> ref_output_data{
- 11, 16, 7, 20, // row = 0
- 0, 40, 0, 44, // row = 1
- };
-
- Tensor input_tensor =
- makeInputTensor<DataType::S16>(input_shape, 0.25, 0, input_data, _memory_manager.get());
- Tensor filter_tensor =
- makeInputTensor<DataType::S16>(filter_shape, 0.2, 0, filter_data, _memory_manager.get());
- Tensor bias_tensor =
- makeInputTensor<DataType::S64>(bias_shape, 0.25 * 0.2, 0, bias_data, _memory_manager.get());
- Tensor im2col(DataType::S16, Shape({}), {}, "");
- Tensor output_tensor = makeOutputTensor(DataType::S16, 0.5, 0);
+ runtime_module.execute();
- Conv2DParams params{};
- params.padding = Padding::VALID;
- params.stride_height = 2;
- params.stride_width = 1;
- params.dilation_height_factor = 1;
- params.dilation_width_factor = 1;
- params.activation = Activation::RELU;
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
- Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- _memory_manager->allocate_memory(im2col);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
- EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST_F(Conv2DTest, SInt16_CWQ_weights)
+TEST_F(Conv2DTest, Float_P)
{
- Shape input_shape{1, 2, 2, 2}; // Batch x H x W x C
- Shape filter_shape{3, 1, 1, 2}; // Out channels x H x W x In Channels
- Shape bias_shape{3};
- std::vector<int32_t> ref_output_shape{1, 2, 2, 3};
-
- std::vector<float> input_data{
- 1, 2, // row = 0, col 0
- 3, 4, // row = 0, col 1
- 5, 6, // row = 1, col 0
- 7, 8, // row = 1, col 1
- };
- std::vector<float> filter_data{
- 4, -3, // out = 0
- 1, -3, // out = 1
- 5, -3, // out = 2
- };
- std::vector<float> bias_data{1, 10, 5};
- std::vector<float> ref_output_data{
- 0, 5, 4, // row 0, col 0
- 1, 1, 8, // row 0, col 1
- 3, 0, 12, // row 1, col 0
- 5, 0, 16, // row 1, col 1
- };
-
- float input_scale = 0.25f;
- float output_scale = 0.05f;
- std::vector<float> filter_scales = {0.25f, 0.2f, 0.1f};
- std::vector<float> bias_scales;
- for (int i = 0; i < filter_scales.size(); ++i)
- bias_scales.push_back(filter_scales[i] * input_scale);
- std::vector<int32_t> zerop = {0, 0, 0};
-
- Tensor input_tensor =
- makeInputTensor<DataType::S16>(input_shape, input_scale, 0, input_data, _memory_manager.get());
- Tensor filter_tensor = makeInputTensor<DataType::S16>(filter_shape, filter_scales, zerop, 0,
- filter_data, _memory_manager.get());
- Tensor bias_tensor = makeInputTensor<DataType::S64>(bias_shape, bias_scales, zerop, 0, bias_data,
- _memory_manager.get());
- Tensor im2col(DataType::S16, Shape({}), {}, "");
- Tensor output_tensor = makeOutputTensor(DataType::S16, output_scale, 0);
-
- Conv2DParams params{};
- params.padding = Padding::VALID;
- params.stride_height = 1;
- params.stride_width = 1;
- params.dilation_height_factor = 1;
- params.dilation_width_factor = 1;
- params.activation = Activation::RELU;
-
- Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- _memory_manager->allocate_memory(im2col);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
- EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
+ test_kernel::TestDataFloatConv2D test_data_kernel;
+ std::vector<float> output_data_vector = checkConv2DKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+ test_data_kernel.get_output_data_by_index(0), 0.0001f));
}
-TEST_F(Conv2DTest, Unsupported_Type_Configure_NEG)
+TEST_F(Conv2DTest, U8_P)
{
- Shape input_shape{1, 4, 3, 2};
- Shape filter_shape{2, 2, 2, 2};
- Shape bias_shape{2};
- std::vector<int32_t> input_data{
- 1, 2, 3, 4, 5, 6, // row = 0
- 7, 8, 9, 10, 11, 12, // row = 1
- 13, 14, 15, 16, 17, 18, // row = 2
- 19, 20, 21, 22, 23, 24, // row = 3
- };
- std::vector<float> filter_data{
- 1, 2, -3, -4, // out = 0, row = 0
- -5, 6, -7, 8, // out = 1, row = 0
- 4, -2, 3, -1, // out = 0, row = 1
- -8, -6, 7, 5, // out = 1, row = 1
- };
- std::vector<float> bias_data{1, 2};
- Tensor input_tensor =
- makeInputTensor<DataType::S32>(input_shape, input_data, _memory_manager.get());
- Tensor filter_tensor =
- makeInputTensor<DataType::FLOAT32>(filter_shape, filter_data, _memory_manager.get());
- Tensor bias_tensor =
- makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data, _memory_manager.get());
- Tensor im2col(DataType::FLOAT32, Shape({}), {}, "");
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- Conv2DParams params{};
- params.padding = Padding::VALID;
- params.stride_height = 2;
- params.stride_width = 1;
- params.dilation_height_factor = 1;
- params.dilation_width_factor = 1;
- params.activation = Activation::RELU;
-
- Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::TestDataU8Conv2D test_data_kernel;
+ std::vector<uint8_t> output_data_vector = checkConv2DKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-TEST_F(Conv2DTest, Invalid_Bias_Type_NEG)
+TEST_F(Conv2DTest, Input_type_mismatch_NEG)
{
- Shape input_shape{1, 4, 3, 2};
- Shape filter_shape{2, 2, 2, 2};
- Shape bias_shape{2};
- std::vector<float> input_data{
- 1, 2, 3, 4, 5, 6, // row = 0
- 7, 8, 9, 10, 11, 12, // row = 1
- 13, 14, 15, 16, 17, 18, // row = 2
- 19, 20, 21, 22, 23, 24, // row = 3
- };
- std::vector<float> filter_data{
- 1, 2, -3, -4, // out = 0, row = 0
- -5, 6, -7, 8, // out = 1, row = 0
- 4, -2, 3, -1, // out = 0, row = 1
- -8, -6, 7, 5, // out = 1, row = 1
- };
- std::vector<uint8_t> bias_data{1, 2};
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
- Tensor filter_tensor =
- makeInputTensor<DataType::FLOAT32>(filter_shape, filter_data, _memory_manager.get());
- Tensor bias_tensor = makeInputTensor<DataType::U8>(bias_shape, bias_data, _memory_manager.get());
- Tensor im2col(DataType::FLOAT32, Shape({}), {}, "");
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+ test_kernel::NegTestDataInputMismatchConv2DKernel test_data_kernel;
- Conv2DParams params{};
- params.padding = Padding::VALID;
- params.stride_height = 2;
- params.stride_width = 1;
- params.dilation_height_factor = 1;
- params.dilation_width_factor = 1;
- params.activation = Activation::RELU;
-
- Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
- EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(Conv2DTest, Invalid_Bias_Data_NEG)
-{
- Shape input_shape{1, 4, 3, 2};
- Shape filter_shape{2, 2, 2, 2};
- Shape bias_shape{3};
- std::vector<float> input_data{
- 1, 2, 3, 4, 5, 6, // row = 0
- 7, 8, 9, 10, 11, 12, // row = 1
- 13, 14, 15, 16, 17, 18, // row = 2
- 19, 20, 21, 22, 23, 24, // row = 3
- };
- std::vector<float> filter_data{
- 1, 2, -3, -4, // out = 0, row = 0
- -5, 6, -7, 8, // out = 1, row = 0
- 4, -2, 3, -1, // out = 0, row = 1
- -8, -6, 7, 5, // out = 1, row = 1
- };
- std::vector<float> bias_data{1, 2, 3};
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
- Tensor filter_tensor =
- makeInputTensor<DataType::FLOAT32>(filter_shape, filter_data, _memory_manager.get());
- Tensor bias_tensor =
- makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data, _memory_manager.get());
- Tensor im2col(DataType::FLOAT32, Shape({}), {}, "");
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- Conv2DParams params{};
- params.padding = Padding::VALID;
- params.stride_height = 2;
- params.stride_width = 1;
- params.dilation_height_factor = 1;
- params.dilation_width_factor = 1;
- params.activation = Activation::RELU;
-
- Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
- EXPECT_ANY_THROW(kernel.configure());
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST_F(Conv2DTest, Invalid_Input_Shape_NEG)
+TEST_F(Conv2DTest, Wrong_bias_type_NEG)
{
- Shape input_shape{1, 4, 6, 1};
- Shape filter_shape{2, 2, 2, 2};
- Shape bias_shape{2};
- std::vector<float> input_data{
- 1, 2, 3, 4, 5, 6, // row = 0
- 7, 8, 9, 10, 11, 12, // row = 1
- 13, 14, 15, 16, 17, 18, // row = 2
- 19, 20, 21, 22, 23, 24, // row = 3
- };
- std::vector<float> filter_data{
- 1, 2, -3, -4, // out = 0, row = 0
- -5, 6, -7, 8, // out = 1, row = 0
- 4, -2, 3, -1, // out = 0, row = 1
- -8, -6, 7, 5, // out = 1, row = 1
- };
- std::vector<float> bias_data{1, 2};
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
- Tensor filter_tensor =
- makeInputTensor<DataType::FLOAT32>(filter_shape, filter_data, _memory_manager.get());
- Tensor bias_tensor =
- makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data, _memory_manager.get());
- Tensor im2col(DataType::FLOAT32, Shape({}), {}, "");
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+ test_kernel::NegTestDataWrongBiasTypeConv2DKernel test_data_kernel;
- Conv2DParams params{};
- params.padding = Padding::VALID;
- params.stride_height = 2;
- params.stride_width = 1;
- params.dilation_height_factor = 1;
- params.dilation_width_factor = 1;
- params.activation = Activation::RELU;
-
- Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
- EXPECT_ANY_THROW(kernel.configure());
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST_F(Conv2DTest, Invalid_fused_act_tanh_NEG)
+TEST_F(Conv2DTest, Invalid_input_type_NEG)
{
- Shape input_shape{1, 4, 3, 2};
- Shape filter_shape{2, 2, 2, 2};
- Shape bias_shape{2};
- std::vector<float> input_data{
- 1, 2, 3, 4, 5, 6, // row = 0
- 7, 8, 9, 10, 11, 12, // row = 1
- 13, 14, 15, 16, 17, 18, // row = 2
- 19, 20, 21, 22, 23, 24, // row = 3
- };
- std::vector<float> filter_data{
- 1, 2, -3, -4, // out = 0, row = 0
- -5, 6, -7, 8, // out = 1, row = 0
- 4, -2, 3, -1, // out = 0, row = 1
- -8, -6, 7, 5, // out = 1, row = 1
- };
- std::vector<float> bias_data{1, 2};
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
- Tensor filter_tensor =
- makeInputTensor<DataType::FLOAT32>(filter_shape, filter_data, _memory_manager.get());
- Tensor bias_tensor =
- makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data, _memory_manager.get());
- Tensor im2col(DataType::FLOAT32, Shape({}), {}, "");
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- Conv2DParams params{};
- params.padding = Padding::VALID;
- params.stride_height = 2;
- params.stride_width = 1;
- params.dilation_height_factor = 1;
- params.dilation_width_factor = 1;
- params.activation = Activation::TANH;
+ test_kernel::NegTestDataInvalidInputTypeConv2DKernel test_data_kernel;
- Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
- EXPECT_ANY_THROW(kernel.configure());
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
-#endif
diff --git a/onert-micro/luci-interpreter/src/kernels/DepthToSpace.cpp b/onert-micro/luci-interpreter/src/kernels/DepthToSpace.cpp
index 28f04d19d..937958ba8 100644
--- a/onert-micro/luci-interpreter/src/kernels/DepthToSpace.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/DepthToSpace.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/DepthToSpace.h b/onert-micro/luci-interpreter/src/kernels/DepthToSpace.h
index 42cf19022..63ce37610 100644
--- a/onert-micro/luci-interpreter/src/kernels/DepthToSpace.h
+++ b/onert-micro/luci-interpreter/src/kernels/DepthToSpace.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/DepthToSpace.test.cpp b/onert-micro/luci-interpreter/src/kernels/DepthToSpace.test.cpp
index f367c1b3e..88e6e07f1 100644
--- a/onert-micro/luci-interpreter/src/kernels/DepthToSpace.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/DepthToSpace.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/DepthwiseConv2D.h b/onert-micro/luci-interpreter/src/kernels/DepthwiseConv2D.h
index daa150596..3d1faf6c1 100644
--- a/onert-micro/luci-interpreter/src/kernels/DepthwiseConv2D.h
+++ b/onert-micro/luci-interpreter/src/kernels/DepthwiseConv2D.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/DepthwiseConv2D.test.cpp b/onert-micro/luci-interpreter/src/kernels/DepthwiseConv2D.test.cpp
index a6e31825c..6b4673f3e 100644
--- a/onert-micro/luci-interpreter/src/kernels/DepthwiseConv2D.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/DepthwiseConv2D.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Dequantize.cpp b/onert-micro/luci-interpreter/src/kernels/Dequantize.cpp
index 5d4b17d98..a0973423d 100644
--- a/onert-micro/luci-interpreter/src/kernels/Dequantize.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Dequantize.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Dequantize.h b/onert-micro/luci-interpreter/src/kernels/Dequantize.h
index 5d671f348..5565df0e4 100644
--- a/onert-micro/luci-interpreter/src/kernels/Dequantize.h
+++ b/onert-micro/luci-interpreter/src/kernels/Dequantize.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Div.cpp b/onert-micro/luci-interpreter/src/kernels/Div.cpp
index d1cd7f70d..f8a469061 100644
--- a/onert-micro/luci-interpreter/src/kernels/Div.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Div.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,140 +14,64 @@
* limitations under the License.
*/
-#include "kernels/Div.h"
-
+#include "Builders.h"
#include "kernels/Utils.h"
-#include <tensorflow/lite/kernels/internal/reference/div.h>
-#include <tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h>
+#include "kernels/BinaryOpCommon.h"
-namespace luci_interpreter
-{
-namespace kernels
-{
+#include "PALDiv.h"
-Div::Div(const Tensor *input1, const Tensor *input2, Tensor *output, const DivParams &params)
- : KernelWithParams<DivParams>({input1, input2}, {output}, params)
+namespace luci_interpreter
{
-}
-void Div::configure()
+// TODO: reduce code duplication with Mul
+void configure_kernel_CircleDiv(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- LUCI_INTERPRETER_CHECK(input1()->element_type() == input2()->element_type());
- LUCI_INTERPRETER_CHECK(input1()->element_type() == output()->element_type());
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(calculateShapeForBroadcast(input1()->shape(), input2()->shape()));
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+ Tensor::element_type(kernel.input2()));
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+ Tensor::element_type(kernel.input2()));
}
-void Div::execute() const
+void execute_kernel_CircleDiv(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- switch (input1()->element_type())
- {
- case DataType::FLOAT32:
- evalFloat();
- break;
- case DataType::S64:
- evalInteger<int64_t>();
- break;
- case DataType::S32:
- evalInteger<int32_t>();
- break;
- case DataType::U8:
- evalQuantized();
- break;
- default:
- assert(false && "Unsupported type.");
- }
-}
-
-void Div::evalFloat() const
-{
- tflite::ArithmeticParams params{};
- fillArithmeticActivationRange<float>(params, _params.activation);
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
- const bool need_broadcast = tflite::reference_ops::ProcessBroadcastShapes(
- getTensorShape(input1()), getTensorShape(input2()), &params);
-
- if (need_broadcast)
- {
- tflite::reference_ops::BroadcastDivSlow(
- params, getTensorShape(input1()), getTensorData<float>(input1()), getTensorShape(input2()),
- getTensorData<float>(input2()), getTensorShape(output()), getTensorData<float>(output()));
- }
- else
- {
- tflite::reference_ops::Div(params, getTensorShape(input1()), getTensorData<float>(input1()),
- getTensorShape(input2()), getTensorData<float>(input2()),
- getTensorShape(output()), getTensorData<float>(output()));
- }
-}
+ const auto *options = cur_op->builtin_options_as_DivOptions();
-template <typename T> void Div::evalInteger() const
-{
- tflite::ArithmeticParams params{};
- fillArithmeticActivationRange<T>(params, _params.activation);
+ luci_interpreter::RuntimeShape input_shape1 =
+ kernels::getTensorRuntimeShape(kernel.input1(), runtime_graph);
+ luci_interpreter::RuntimeShape input_shape2 =
+ kernels::getTensorRuntimeShape(kernel.input2(), runtime_graph);
- const bool need_broadcast = tflite::reference_ops::ProcessBroadcastShapes(
- getTensorShape(input1()), getTensorShape(input2()), &params);
+ bool is_inplace = runtime_graph->is_inplace_op(cur_op);
- if (need_broadcast)
+ switch (Tensor::element_type(kernel.input1()))
{
- tflite::reference_ops::BroadcastDivSlow(
- params, getTensorShape(input1()), getTensorData<T>(input1()), getTensorShape(input2()),
- getTensorData<T>(input2()), getTensorShape(output()), getTensorData<T>(output()));
- }
- else
- {
- tflite::reference_ops::Div(params, getTensorShape(input1()), getTensorData<T>(input1()),
- getTensorShape(input2()), getTensorData<T>(input2()),
- getTensorShape(output()), getTensorData<T>(output()));
- }
-}
-
-void Div::evalQuantized() const
-{
- const auto input1_scale = static_cast<double>(input1()->scale());
- const auto input2_scale = static_cast<double>(input2()->scale());
- const auto output_scale = static_cast<double>(output()->scale());
-
- const double real_output_multiplier = input1_scale / (input2_scale * output_scale);
-
- int32_t output_multiplier{};
- int output_shift{};
-
- quantizeMultiplier(real_output_multiplier, &output_multiplier, &output_shift);
-
- int32_t activation_min{};
- int32_t activation_max{};
- calculateActivationRangeQuantized(_params.activation, output(), &activation_min, &activation_max);
-
- tflite::ArithmeticParams params{};
-
- params.input1_offset = -input1()->zero_point(); // Note the '-'.
- params.input2_offset = -input2()->zero_point(); // Note the '-'.
- params.output_offset = output()->zero_point();
- params.output_multiplier = output_multiplier;
- params.output_shift = output_shift;
- params.quantized_activation_min = activation_min;
- params.quantized_activation_max = activation_max;
-
- const bool need_broadcast = tflite::reference_ops::ProcessBroadcastShapes(
- getTensorShape(input1()), getTensorShape(input2()), &params);
-
- if (need_broadcast)
- {
- tflite::reference_ops::BroadcastDivSlow(
- params, getTensorShape(input1()), getTensorData<uint8_t>(input1()), getTensorShape(input2()),
- getTensorData<uint8_t>(input2()), getTensorShape(output()), getTensorData<uint8_t>(output()));
- }
- else
- {
- tflite::reference_ops::Div(params, getTensorShape(input1()), getTensorData<uint8_t>(input1()),
- getTensorShape(input2()), getTensorData<uint8_t>(input2()),
- getTensorShape(output()), getTensorData<uint8_t>(output()));
+#ifndef DIS_FLOAT
+ case DataType::FLOAT32:
+ {
+ auto tiso_func = luci_interpreter_pal::Div<float>;
+ auto broadcast_tiso_func = luci_interpreter_pal::BroadcastDiv4DSlow<float>;
+ if (is_inplace)
+ {
+ kernels::evalTISOInplaceKernel<float>(tiso_func, broadcast_tiso_func, &kernel, options,
+ std::move(input_shape1), std::move(input_shape2));
+ }
+ else
+ {
+ kernels::TISOData kernel_data = kernel.readData();
+ kernels::evalTISOKernel<float>(tiso_func, broadcast_tiso_func, &kernel, &kernel_data,
+ options, std::move(input_shape1), std::move(input_shape2));
+ }
+ }
+ break;
+#endif // DIS_FLOAT
+ default:
+ assert(false && "Unsupported type.");
}
}
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Div.h b/onert-micro/luci-interpreter/src/kernels/Div.h
deleted file mode 100644
index ac8866147..000000000
--- a/onert-micro/luci-interpreter/src/kernels/Div.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_DIV_H
-#define LUCI_INTERPRETER_KERNELS_DIV_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Div : public KernelWithParams<DivParams>
-{
-public:
- Div(const Tensor *input1, const Tensor *input2, Tensor *output, const DivParams &params);
-
- const Tensor *input1() const { return _inputs[0]; }
- const Tensor *input2() const { return _inputs[1]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-
-private:
- void evalFloat() const;
- template <typename T> void evalInteger() const;
- void evalQuantized() const;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_DIV_H
diff --git a/onert-micro/luci-interpreter/src/kernels/Div.test.cpp b/onert-micro/luci-interpreter/src/kernels/Div.test.cpp
index 85cd8b90a..d6014397c 100644
--- a/onert-micro/luci-interpreter/src/kernels/Div.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Div.test.cpp
@@ -15,14 +15,14 @@
* limitations under the License.
*/
-#include "kernels/Div.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/div/FloatDivKernel.h"
+#include "luci_interpreter/test_models/div/NegDivKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
@@ -30,201 +30,93 @@ using namespace testing;
class DivTest : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-float GetTolerance(float min, float max)
-{
- const float kQuantizedStep = (max - min) / 255.0f;
- const float kQuantizedTolerance = 2.0f * kQuantizedStep + kQuantizedStep * kQuantizedStep;
- return kQuantizedTolerance;
-}
-
-TEST_F(DivTest, Float)
-{
- Shape base_shape = {2, 3, 1, 1};
-
- std::vector<int32_t> output_shape = {2, 3, 1, 1};
-
- std::vector<float> input1_data{0.3f, 2.3f, 0.9f, 0.5f, 0.8f, 1.1f};
- std::vector<float> input2_data{0.2f, 1.6f, 0.5f, 0.4f, 1.6f, 0.4f};
- std::vector<float> test_outputs{1.5f, 1.4375f, 1.8f, 1.25f, 0.5f, 2.75f};
-
- Tensor input1_tensor =
- makeInputTensor<DataType::FLOAT32>(base_shape, input1_data, _memory_manager.get());
- Tensor input2_tensor =
- makeInputTensor<DataType::FLOAT32>(base_shape, input2_data, _memory_manager.get());
-
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- DivParams params{};
- params.activation = Activation::RELU;
-
- Div kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(test_outputs, 0.0001f));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
-}
-
-TEST_F(DivTest, FloatBroadcast)
-{
- Shape input1_shape = {1, 3};
- Shape input2_shape = {3, 1};
-
- std::vector<float> input1_data{-0.3f, 2.3f, 0.9f};
- std::vector<float> input2_data{0.2f, 1.6f, 0.5f};
- std::vector<float> test_outputs{0.f, 11.5f, 4.5f, 0.f, 1.4375f, 0.5625f, 0.f, 4.6f, 1.8f};
-
- Tensor input1_tensor =
- makeInputTensor<DataType::FLOAT32>(input1_shape, input1_data, _memory_manager.get());
- Tensor input2_tensor =
- makeInputTensor<DataType::FLOAT32>(input2_shape, input2_data, _memory_manager.get());
-
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- DivParams params{};
- params.activation = Activation::RELU;
-
- Div kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(test_outputs, 0.0001f));
-}
-
-TEST_F(DivTest, Uint8)
+template <typename T> std::vector<T> checkDivKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- Shape base_shape = {1, 2, 2, 1};
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- std::vector<int32_t> output_shape = {1, 2, 2, 1};
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- std::vector<float> input1_data = {-0.8f, -0.2f, 0.3f, 0.7f};
- std::vector<float> input2_data = {-0.8f, 0.4f, 0.8f, 1.0f};
- std::vector<float> test_outputs{1.0f, 0.f, 0.375f, 0.7f};
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 2);
- const float kQuantizedTolerance = GetTolerance(-1.0, 1.0);
-
- std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(-1.f, 1.f);
-
- Tensor input1_tensor = makeInputTensor<DataType::U8>(
- base_shape, quant_param.first, quant_param.second, input1_data, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::U8>(
- base_shape, quant_param.first, quant_param.second, input2_data, _memory_manager.get());
+ // set left input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
- Tensor output_tensor =
- makeOutputTensor(getElementType<uint8_t>(), quant_param.first, quant_param.second);
+ // set right input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(1));
+ std::copy(test_data_base->get_input_data_by_index(1).begin(),
+ test_data_base->get_input_data_by_index(1).end(), input_tensor_data);
+ }
- DivParams params{};
- params.activation = Activation::RELU;
+ runtime_module.execute();
- Div kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
- EXPECT_THAT(dequantizeTensorData(output_tensor),
- FloatArrayNear(test_outputs, kQuantizedTolerance));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-template <loco::DataType DType> void checkInteger(luci_interpreter::IMemoryManager *memory_manager)
+TEST_F(DivTest, Float_P)
{
- using dtype = typename loco::DataTypeImpl<DType>::Type;
- Shape base_shape = {2, 3, 1, 2};
- std::vector<Shape> test_shapes{{1, 1, 3, 2}, {1, 3, 1, 2}, {2, 1, 3, 1}, {2, 3, 1, 1}};
-
- std::vector<std::vector<dtype>> test_outputs = {{5, 6, 2, 0, 10, 3, //
- 10, 0, 4, 5, 20, 0, //
- 0, 0, 0, 2, 0, 0, //
- 2, 0, 1, 10, 5, 0, //
- 2, 3, 1, 0, 5, 1, //
- 18, 20, 7, 0, 37, 10},
- {5, 6, 4, 5, 0, 0, 2, 0, 1, 0, 37, 10},
- {5, 7, 4, 6, 2, 3, 10, 0, 8, 0, 4, 0,
- 0, 0, 0, 0, 0, 0, 0, 10, 5, 0, 1, 0,
- 0, 0, 5, 9, 1, 1, 0, 0, 37, 50, 7, 10},
- {5, 7, 8, 0, 0, 0, 0, 10, 5, 9, 7, 10}};
- std::vector<dtype> input1_data{20, 30, 40, -17, -4, -7, 11, -31, 10, 19, 75, 100};
- std::vector<dtype> input2_data{4, 5, 10, -3, 2, 10};
- for (size_t i = 0; i < test_shapes.size(); ++i)
+ // No broadcast
{
- Tensor input1_tensor = makeInputTensor<DType>(base_shape, input1_data, memory_manager);
- Tensor input2_tensor = makeInputTensor<DType>(test_shapes[i], input2_data, memory_manager);
- Tensor output_tensor = makeOutputTensor(DType);
-
- DivParams params{};
- params.activation = Activation::RELU;
-
- Div kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<dtype>(output_tensor), test_outputs[i])
- << "With shape number " << i;
+ const bool is_with_broadcast = false;
+ test_kernel::TestDataFloatDiv test_data_kernel(is_with_broadcast);
+ std::vector<float> output_data_vector = checkDivKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+ test_data_kernel.get_output_data_by_index(0), 0.0001f));
+ }
+ // With broadcast
+ {
+ const bool is_with_broadcast = true;
+ test_kernel::TestDataFloatDiv test_data_kernel(is_with_broadcast);
+ std::vector<float> output_data_vector = checkDivKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+ test_data_kernel.get_output_data_by_index(0), 0.0001f));
}
}
-TEST_F(DivTest, SInt64)
-{
- checkInteger<loco::DataType::S64>(_memory_manager.get());
- SUCCEED();
-}
-
-TEST_F(DivTest, SInt32)
-{
- checkInteger<loco::DataType::S32>(_memory_manager.get());
- SUCCEED();
-}
-
-TEST_F(DivTest, Input_Output_Type_NEG)
+TEST_F(DivTest, Wrong_Input1_Type_NEG)
{
- Tensor input1_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::S32>({1}, {2}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- DivParams params{};
- params.activation = Activation::RELU;
-
- Div kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::NegTestDataInput1WrongTypeDiv test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST_F(DivTest, Invalid_Input_Type_NEG)
+TEST_F(DivTest, Wrong_Input2_Type_NEG)
{
- Tensor input1_tensor = makeInputTensor<DataType::U64>({1}, {1}, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::U64>({1}, {2}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U64);
-
- DivParams params{};
- params.activation = Activation::RELU;
-
- Div kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- EXPECT_ANY_THROW(kernel.execute());
+ test_kernel::NegTestDataInput2WrongTypeDiv test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST_F(DivTest, Invalid_Output_Type_NEG)
-{
- Tensor input1_tensor = makeInputTensor<DataType::S32>({1}, {1}, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::S32>({1}, {2}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S64);
-
- DivParams params{};
- params.activation = Activation::RELU;
-
- Div kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
-}
+// TODO: add tests for inplace optimizations for all types
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Elu.cpp b/onert-micro/luci-interpreter/src/kernels/Elu.cpp
index 160a1a58e..3c3459178 100644
--- a/onert-micro/luci-interpreter/src/kernels/Elu.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Elu.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,38 +14,63 @@
* limitations under the License.
*/
-#include "kernels/Elu.h"
+#include "Builders.h"
#include "kernels/Utils.h"
+#include "SISOKernel.h"
#include "PALElu.h"
namespace luci_interpreter
{
-namespace kernels
+void configure_kernel_CircleElu(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
+ kernels::SISOKernel kernel(cur_op, runtime_graph);
-Elu::Elu(const Tensor *input, Tensor *output) : Kernel({input}, {output}) {}
-
-void Elu::configure()
-{
- LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(input()->shape());
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input()) ==
+ Tensor::element_type(kernel.output()));
+ LUCI_INTERPRETER_CHECK(Tensor::num_elements(kernel.input()) ==
+ Tensor::num_elements(kernel.output()));
+ LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.input()) == Tensor::num_dims(kernel.output()));
}
-void Elu::execute() const
+void execute_kernel_CircleElu(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- switch (input()->element_type())
+ kernels::SISOKernel kernel(cur_op, runtime_graph);
+
+ const auto *input_data = runtime_graph->getDataByTensor(kernel.input());
+ assert(input_data);
+
+ auto *output_data = runtime_graph->getDataByTensor(kernel.output());
+
+ bool is_inplace = runtime_graph->is_inplace_op(cur_op);
+
+ switch (Tensor::element_type(kernel.input()))
{
+#ifndef DIS_FLOAT
case DataType::FLOAT32:
- luci_interpreter_pal::Elu(getTensorShape(input()), getTensorData<float>(input()),
- getTensorShape(output()), getTensorData<float>(output()));
+ {
+ const float *input_data_float = kernels::getTensorData<float>(input_data);
+ float *output_data_float = kernels::getTensorData<float>(output_data);
+ if (is_inplace)
+ {
+ output_data_float = const_cast<float *>(input_data_float);
+ }
+
+ assert(output_data_float);
+
+ const int flat_size =
+ kernels::getTensorRuntimeShape(kernel.input(), runtime_graph).flatSize();
+
+ luci_interpreter_pal::Elu(flat_size, input_data_float, output_data_float);
break;
+ }
+#endif // DIS_FLOAT
default:
- assert(false && "Unsupported type.");
+ assert(false && "Unsupported type");
}
-}
-} // namespace kernels
+ if (is_inplace)
+ runtime_graph->makeInplaceOperation(kernel.input(), kernel.output());
+}
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Elu.test.cpp b/onert-micro/luci-interpreter/src/kernels/Elu.test.cpp
index b87d687c4..71a9692c3 100644
--- a/onert-micro/luci-interpreter/src/kernels/Elu.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Elu.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,68 +14,73 @@
* limitations under the License.
*/
-#include "kernels/Elu.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/elu/FloatEluKernel.h"
+#include "luci_interpreter/test_models/elu/NegEluKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
using namespace testing;
-void Check(std::initializer_list<int32_t> input_shape, std::initializer_list<int32_t> output_shape,
- std::initializer_list<float> input_data, std::initializer_list<float> output_data)
+class EluTest : public ::testing::Test
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+ // Do nothing
+};
+
+template <typename T> std::vector<T> checkEluKernel(test_kernel::TestDataBase<T> *test_data_base)
+{
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- Elu kernel(&input_tensor, &output_tensor);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
- (void)output_shape;
- EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(output_data));
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
+
+ runtime_module.execute();
+
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
+
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST(EluTest, SimpleElu)
+TEST_F(EluTest, Float_P)
{
- Check(
- /*input_shape=*/{1, 2, 4, 1}, /*output_shape=*/{1, 2, 4, 1},
- /*input_data=*/
- {
- 0, -6, 2, -4, //
- 3, -2, 10, -0.1, //
- },
- /*output_data=*/
- {
- 0.0, -0.997521, 2.0, -0.981684, //
- 3.0, -0.864665, 10.0, -0.0951626, //
- });
+ test_kernel::TestDataFloatElu test_data_kernel;
+ std::vector<float> output_data_vector = checkEluKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+ test_data_kernel.get_output_data_by_index(0), 0.0001f));
}
-TEST(EluTest, InOutTypeMismatch_NEG)
+TEST_F(EluTest, Input_output_type_mismatch_NEG)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- Shape input_shape{1, 2, 4, 1};
- std::vector<float> input_data{
- 0, -6, 2, -4, //
- 3, -2, 10, -0.1, //
- };
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U8);
-
- Elu kernel(&input_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::NegTestDataInputOutputTypeMismatchEluKernel test_data_kernel;
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Equal.cpp b/onert-micro/luci-interpreter/src/kernels/Equal.cpp
index 003d64354..76968a364 100644
--- a/onert-micro/luci-interpreter/src/kernels/Equal.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Equal.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,128 +14,84 @@
* limitations under the License.
*/
-#include "kernels/Equal.h"
+#include "Builders.h"
#include "kernels/Utils.h"
+#include "TISOKernel.h"
-#include <tensorflow/lite/kernels/internal/reference/comparisons.h>
+#include "PALComparisons.h"
namespace luci_interpreter
{
-namespace kernels
+namespace
{
-
-Equal::Equal(const Tensor *x, const Tensor *y, Tensor *output) : Kernel({x, y}, {output}) {}
-
-void Equal::configure()
+// TODO: reduce code duplication with less
+template <typename T>
+void evalGeneric(const circle::Tensor *x, const circle::Tensor *y, const circle::Tensor *output,
+ BaseRuntimeGraph *runtime_graph)
{
- LUCI_INTERPRETER_CHECK(x()->element_type() == y()->element_type());
- LUCI_INTERPRETER_CHECK(output()->element_type() == DataType::BOOL);
+ auto x_data = kernels::getTensorData<T>(runtime_graph->getDataByTensor(x));
+ if (x_data == nullptr)
+ x_data = kernels::getTensorData<T>(runtime_graph->getConstDataByTensor(x));
- if (x()->element_type() == DataType::U8)
- {
- quantizeMultiplierSmallerThanOneExp(x()->scale(), &_x_multiplier, &_x_shift);
- quantizeMultiplierSmallerThanOneExp(y()->scale(), &_y_multiplier, &_y_shift);
- }
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(calculateShapeForBroadcast(x()->shape(), y()->shape()));
-}
+ assert(x_data != nullptr);
-void Equal::execute() const
-{
- switch (x()->element_type())
- {
- case DataType::FLOAT32:
- evalFloat();
- break;
- case DataType::S64:
- evalInteger<int64_t>();
- break;
- case DataType::S32:
- evalInteger<int32_t>();
- break;
- case DataType::U8:
- evalQuantized();
- break;
- default:
- assert(false && "Unsupported type.");
- }
-}
+ auto y_data = kernels::getTensorData<T>(runtime_graph->getDataByTensor(y));
+ if (y_data == nullptr)
+ y_data = kernels::getTensorData<T>(runtime_graph->getConstDataByTensor(y));
-void Equal::evalFloat() const
-{
- const auto x_data = getTensorData<float>(x());
- const auto y_data = getTensorData<float>(y());
- auto output_data = getTensorData<bool>(output());
+ assert(y_data != nullptr);
+
+ auto output_data = kernels::getTensorData<bool>(runtime_graph->getDataByTensor(output));
- tflite::ComparisonParams op_params;
- op_params.is_broadcast = x()->shape() != y()->shape();
+ luci_interpreter_pal::ComparisonParams op_params;
+ op_params.is_broadcast = Tensor::num_elements(x) != Tensor::num_elements(y);
if (op_params.is_broadcast)
{
- tflite::reference_ops::Broadcast4DSlowEqual(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data,
- getTensorShape(output()), output_data);
+ luci_interpreter_pal::BroadcastComparison4DSlowNoScaling<T>(
+ op_params, kernels::getTensorShape(x), x_data, kernels::getTensorShape(y), y_data,
+ kernels::getTensorShape(output), output_data, luci_interpreter_pal::EqualFn);
}
else
{
- tflite::reference_ops::Equal(op_params, getTensorShape(x()), x_data, getTensorShape(y()),
- y_data, getTensorShape(output()), output_data);
+ const int64_t flat_size = kernels::getTensorShape(x).flatSize();
+ luci_interpreter_pal::ComparisonNoScaling<T>(flat_size, x_data, y_data, output_data,
+ luci_interpreter_pal::EqualFn);
}
}
-template <typename T> void Equal::evalInteger() const
-{
- const auto x_data = getTensorData<T>(x());
- const auto y_data = getTensorData<T>(y());
- auto output_data = getTensorData<bool>(output());
+} // namespace
- tflite::ComparisonParams op_params;
- op_params.is_broadcast = x()->shape() != y()->shape();
+void configure_kernel_CircleEqual(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
- if (op_params.is_broadcast)
- {
- tflite::reference_ops::Broadcast4DSlowEqualNoScaling(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data,
- getTensorShape(output()), output_data);
- }
- else
- {
- tflite::reference_ops::EqualNoScaling(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data, getTensorShape(output()),
- output_data);
- }
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+ Tensor::element_type(kernel.input2()));
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.output()) == DataType::BOOL);
}
-void Equal::evalQuantized() const
+void execute_kernel_CircleEqual(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- const auto x_data = getTensorData<uint8_t>(x());
- const auto y_data = getTensorData<uint8_t>(y());
- auto output_data = getTensorData<bool>(output());
-
- tflite::ComparisonParams op_params;
- op_params.left_shift = 8;
- op_params.input1_offset = -x()->zero_point(); // Note the '-'
- op_params.input1_shift = _x_shift;
- op_params.input1_multiplier = _x_multiplier;
- op_params.input2_offset = -y()->zero_point(); // Note the '-'
- op_params.input2_shift = _y_shift;
- op_params.input2_multiplier = _y_multiplier;
- op_params.is_broadcast = x()->shape() != y()->shape();
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
- if (op_params.is_broadcast)
- {
- tflite::reference_ops::Broadcast4DSlowEqualWithScaling(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data,
- getTensorShape(output()), output_data);
- }
- else
+ switch (Tensor::element_type(kernel.input1()))
{
- tflite::reference_ops::EqualWithScaling(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data, getTensorShape(output()),
- output_data);
+ case DataType::S64:
+ evalGeneric<int64_t>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+ break;
+ case DataType::S32:
+ evalGeneric<int32_t>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+ break;
+#ifndef DIS_FLOAT
+ case DataType::FLOAT32:
+ evalGeneric<float>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+ break;
+#endif // DIS_FLOAT
+ default:
+ assert(false && "Unsupported type.");
}
}
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Equal.h b/onert-micro/luci-interpreter/src/kernels/Equal.h
deleted file mode 100644
index 7c5f38004..000000000
--- a/onert-micro/luci-interpreter/src/kernels/Equal.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_EQUAL_H
-#define LUCI_INTERPRETER_KERNELS_EQUAL_H
-
-#include "core/Kernel.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Equal : public Kernel
-{
-public:
- Equal(const Tensor *x, const Tensor *y, Tensor *output);
-
- const Tensor *x() const { return _inputs[0]; }
- const Tensor *y() const { return _inputs[1]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-
-private:
- void evalFloat() const;
- template <typename T> void evalInteger() const;
- void evalQuantized() const;
-
-private:
- int32_t _x_multiplier = 0;
- int _x_shift = 0;
- int32_t _y_multiplier = 0;
- int _y_shift = 0;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_EQUAL_H
diff --git a/onert-micro/luci-interpreter/src/kernels/Equal.test.cpp b/onert-micro/luci-interpreter/src/kernels/Equal.test.cpp
index 5870e5460..15bcd1919 100644
--- a/onert-micro/luci-interpreter/src/kernels/Equal.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Equal.test.cpp
@@ -15,14 +15,14 @@
* limitations under the License.
*/
-#include "kernels/Equal.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/equal/FloatEqualKernel.h"
+#include "luci_interpreter/test_models/equal/IntEqualKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
@@ -30,277 +30,106 @@ using namespace testing;
class EqualTest : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-TEST_F(EqualTest, FloatSimple)
-{
- std::vector<float> x_data{
- 0.5, 0.7, 0.9, // Row 1
- 1, 0, -1, // Row 2
- };
-
- std::vector<float> y_data{
- 0.9, 0.7, 0.5, // Row 1
- -1, 0, 1, // Row 2
- };
-
- std::vector<bool> ref_output_data{
- false, true, false, // Row 1
- false, true, false, // Row 2
- };
-
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Equal kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({2, 3}));
-}
-
-TEST_F(EqualTest, FloatBroardcast)
+template <typename T, typename U>
+std::vector<U> checkEqualKernel(test_kernel::TestDataBase<T, U> *test_data_base)
{
- std::vector<float> x_data{
- 0.5, 0.7, 0.9, // Row 1
- 1, 0, -1, // Row 2
- -1, 0, 1, // Row 3
- 0.9, 0.7, 0.5, // Row 4
- };
-
- std::vector<float> y_data{
- 0.9, 0.7, 0.5, // Row 1
- };
-
- std::vector<bool> ref_output_data{
- false, true, false, // Row 1
- false, false, false, // Row 2
- false, false, false, // Row 3
- true, true, true, // Row 4
- };
-
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({4, 3}, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({1, 3}, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Equal kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({4, 3}));
-}
-
-template <loco::DataType DType>
-void checkIntegerSimple(luci_interpreter::IMemoryManager *memory_manager)
-{
- using dtype = typename loco::DataTypeImpl<DType>::Type;
- dtype min_value = std::numeric_limits<dtype>::min();
- dtype max_value = std::numeric_limits<dtype>::max();
- std::vector<dtype> x_data{min_value, 2, max_value};
-
- std::vector<dtype> y_data{min_value, -2, max_value};
-
- std::vector<bool> ref_output_data{true, false, true};
-
- Tensor x_tensor = makeInputTensor<DType>({3}, x_data, memory_manager);
- Tensor y_tensor = makeInputTensor<DType>({3}, y_data, memory_manager);
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Equal kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({3}));
-}
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
-template <loco::DataType DType>
-void checkIntegerBroadcast(luci_interpreter::IMemoryManager *memory_manager)
-{
- using dtype = typename loco::DataTypeImpl<DType>::Type;
- dtype min_value = std::numeric_limits<dtype>::min();
- dtype max_value = std::numeric_limits<dtype>::max();
- std::vector<dtype> x_data{
- min_value, 2, 3, // Row 1
- 4, 5, max_value, // Row 2
- -1, -2, -3, // Row 3
- min_value, -2, max_value, // Row 4
- };
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 2);
- std::vector<dtype> y_data{
- min_value, -2, max_value, // Row 1
- };
+ // set left input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
- std::vector<bool> ref_output_data{
- true, false, false, // Row 1
- false, false, true, // Row 2
- false, true, false, // Row 3
- true, true, true, // Row 4
- };
+ // set right input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(1));
+ std::copy(test_data_base->get_input_data_by_index(1).begin(),
+ test_data_base->get_input_data_by_index(1).end(), input_tensor_data);
+ }
- Tensor x_tensor = makeInputTensor<DType>({4, 3}, x_data, memory_manager);
- Tensor y_tensor = makeInputTensor<DType>({3}, y_data, memory_manager);
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
+ runtime_module.execute();
- Equal kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({4, 3}));
+ U *output_data = reinterpret_cast<U *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(U));
+ std::vector<U> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST_F(EqualTest, Int32)
+TEST_F(EqualTest, FloatNoBroadcast_P)
{
- checkIntegerSimple<loco::DataType::S32>(_memory_manager.get());
- checkIntegerBroadcast<loco::DataType::S32>(_memory_manager.get());
- SUCCEED();
+ const bool is_with_broadcast = false;
+ test_kernel::TestDataFloatEqual test_data_kernel(is_with_broadcast, false);
+ std::vector<bool> output_data_vector = checkEqualKernel<float, bool>(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-TEST_F(EqualTest, Int64)
+TEST_F(EqualTest, FloatWithBroadcast_P)
{
- checkIntegerSimple<loco::DataType::S64>(_memory_manager.get());
- checkIntegerBroadcast<loco::DataType::S64>(_memory_manager.get());
- SUCCEED();
+ const bool is_with_broadcast = true;
+ test_kernel::TestDataFloatEqual test_data_kernel(is_with_broadcast, false);
+ std::vector<bool> output_data_vector = checkEqualKernel<float, bool>(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-// Choose min / max in such a way that there are exactly 256 units to avoid rounding errors.
-const float F_MIN = -128.0 / 128.0;
-const float F_MAX = 127.0 / 128.0;
-
-TEST_F(EqualTest, Uint8Quantized)
+TEST_F(EqualTest, FloatNoBroadcast_NEG)
{
- std::vector<float> x_data{
- 0.5, 0.5, 0.7, 0.9, // Row 1
- 1, 0, 0.05, -1, // Row 2
- };
-
- std::vector<float> y_data{
- 0.9, 0.5, 0.55, 0.5, // Row 1
- -1, 0, 0.05, 1, // Row 2
- };
-
- std::vector<bool> ref_output_data{
- false, true, false, false, // Row 1
- false, true, true, false, // Row 2
- };
-
- std::pair<float, int32_t> x_quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
- Tensor x_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, x_quant_param.first, x_quant_param.second, x_data, _memory_manager.get());
-
- std::pair<float, int32_t> y_quant_param = quantizationParams<uint8_t>(F_MIN * 2, F_MAX * 2);
- Tensor y_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, y_quant_param.first, y_quant_param.second, y_data, _memory_manager.get());
-
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Equal kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 4, 1}));
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
+ const bool is_with_broadcast = false;
+ test_kernel::TestDataFloatEqual test_data_kernel(is_with_broadcast, true);
+ EXPECT_DEATH(checkEqualKernel(&test_data_kernel), "");
}
-TEST_F(EqualTest, Uint8QuantizedBroadcast)
+TEST_F(EqualTest, FloatWithBroadcast_NEG)
{
- std::vector<float> x_data{
- 0.4, -0.8, 0.7, 0.3, // Row 1
- -0.5, 0.1, 0, 0.5, // Row 2
- 1, 0, 0.05, -1, // Row 3
- -1, 0.05, 0, 1, // Row 4
- };
-
- std::vector<float> y_data{
- -1, 0.05, 0, 1, // Row 1
- };
-
- std::vector<bool> ref_output_data{
- false, false, false, false, // Row 1
- false, false, true, false, // Row 2
- false, false, false, false, // Row 3
- true, true, true, true, // Row 4
- };
-
- std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
- Tensor x_tensor = makeInputTensor<DataType::U8>(
- {1, 4, 4, 1}, quant_param.first, quant_param.second, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::U8>(
- {1, 1, 4, 1}, quant_param.first, quant_param.second, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Equal kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 4, 4, 1}));
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
+ const bool is_with_broadcast = true;
+ test_kernel::TestDataFloatEqual test_data_kernel(is_with_broadcast, true);
+ EXPECT_DEATH(checkEqualKernel(&test_data_kernel), "");
}
-TEST_F(EqualTest, Input_Type_Mismatch_NEG)
+TEST_F(EqualTest, IntWithBroadcast_P)
{
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::U8>({1}, {1}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Equal kernel(&x_tensor, &y_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
+ const bool is_with_broadcast = true;
+ test_kernel::TestDataIntEqual test_data_kernel(is_with_broadcast, false);
+ std::vector<bool> output_data_vector = checkEqualKernel<int32_t, bool>(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-TEST_F(EqualTest, Input_Output_Type_NEG)
+TEST_F(EqualTest, IntNoBroadcast_P)
{
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- Equal kernel(&x_tensor, &y_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
+ const bool is_with_broadcast = false;
+ test_kernel::TestDataIntEqual test_data_kernel(is_with_broadcast, false);
+ std::vector<bool> output_data_vector = checkEqualKernel<int32_t, bool>(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-TEST_F(EqualTest, Float_Broadcast_NEG)
+TEST_F(EqualTest, IntWithBroadcast_NEG)
{
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({2}, {1.f, 2.f}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({3}, {1.f, 2.f, 3.f}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Equal kernel(&x_tensor, &y_tensor, &output_tensor);
- ASSERT_ANY_THROW(kernel.configure());
+ const bool is_with_broadcast = true;
+ test_kernel::TestDataIntEqual test_data_kernel(is_with_broadcast, true);
+ EXPECT_DEATH(checkEqualKernel(&test_data_kernel), "");
}
-TEST_F(EqualTest, Int32_Broadcast_NEG)
+TEST_F(EqualTest, IntNoBroadcast_NEG)
{
- Tensor x_tensor = makeInputTensor<DataType::S32>({2}, {1, 2}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::S32>({3}, {1, 2, 3}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Equal kernel(&x_tensor, &y_tensor, &output_tensor);
- ASSERT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(EqualTest, Int64_Broadcast_NEG)
-{
- Tensor x_tensor = makeInputTensor<DataType::S64>({2}, {1, 2}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::S64>({3}, {1, 2, 3}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Equal kernel(&x_tensor, &y_tensor, &output_tensor);
- ASSERT_ANY_THROW(kernel.configure());
+ const bool is_with_broadcast = false;
+ test_kernel::TestDataIntEqual test_data_kernel(is_with_broadcast, true);
+ EXPECT_DEATH(checkEqualKernel(&test_data_kernel), "");
}
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Exp.cpp b/onert-micro/luci-interpreter/src/kernels/Exp.cpp
index ceb54e71e..b46b354ec 100644
--- a/onert-micro/luci-interpreter/src/kernels/Exp.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Exp.cpp
@@ -15,43 +15,64 @@
* limitations under the License.
*/
-#include "kernels/Exp.h"
-
+#include "Builders.h"
#include "kernels/Utils.h"
+#include "SISOKernel.h"
-#include <tensorflow/lite/kernels/internal/reference/exp.h>
+#include "PALExp.h"
namespace luci_interpreter
{
-namespace kernels
-{
-Exp::Exp(const Tensor *input, Tensor *output) : Kernel({input}, {output}) {}
-
-void Exp::configure()
+void configure_kernel_CircleExp(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(input()->shape());
+ kernels::SISOKernel kernel(cur_op, runtime_graph);
+
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input()) ==
+ Tensor::element_type(kernel.output()));
+ LUCI_INTERPRETER_CHECK(Tensor::num_elements(kernel.input()) ==
+ Tensor::num_elements(kernel.output()));
+ LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.input()) == Tensor::num_dims(kernel.output()));
}
-void Exp::execute() const
+void execute_kernel_CircleExp(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- switch (input()->element_type())
+ kernels::SISOKernel kernel(cur_op, runtime_graph);
+
+ const auto *input_data = runtime_graph->getDataByTensor(kernel.input());
+ assert(input_data);
+
+ auto *output_data = runtime_graph->getDataByTensor(kernel.output());
+
+ bool is_inplace = runtime_graph->is_inplace_op(cur_op);
+
+ switch (Tensor::element_type(kernel.input()))
{
+#ifndef DIS_FLOAT
case DataType::FLOAT32:
- evalFloat();
+ {
+ const float *input_data_float = kernels::getTensorData<float>(input_data);
+ float *output_data_float = kernels::getTensorData<float>(output_data);
+ if (is_inplace)
+ {
+ output_data_float = const_cast<float *>(input_data_float);
+ }
+
+ assert(output_data_float);
+
+ const int flat_size =
+ kernels::getTensorRuntimeShape(kernel.input(), runtime_graph).flatSize();
+
+ luci_interpreter_pal::Exp(flat_size, input_data_float, output_data_float);
break;
+ }
+#endif // DIS_FLOAT
default:
- assert(false && "Unsupported type.");
+ assert(false && "Unsupported type");
}
-}
-void Exp::evalFloat() const
-{
- const int size = tflite::MatchingFlatSize(getTensorShape(input()), getTensorShape(output()));
- tflite::reference_ops::Exp(getTensorData<float>(input()), size, getTensorData<float>(output()));
+ if (is_inplace)
+ runtime_graph->makeInplaceOperation(kernel.input(), kernel.output());
}
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Exp.test.cpp b/onert-micro/luci-interpreter/src/kernels/Exp.test.cpp
index a159d9db9..21d21e7e2 100644
--- a/onert-micro/luci-interpreter/src/kernels/Exp.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Exp.test.cpp
@@ -15,41 +15,73 @@
* limitations under the License.
*/
-#include "kernels/Exp.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/exp/FloatExpKernel.h"
+#include "luci_interpreter/test_models/exp/NegExpKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
using namespace testing;
-TEST(ExpTest, Float)
+class ExpTest : public ::testing::Test
+{
+ // Do nothing
+};
+
+template <typename T> std::vector<T> checkExpKernel(test_kernel::TestDataBase<T> *test_data_base)
+{
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
+
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
+
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
+
+ runtime_module.execute();
+
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
+
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
+}
+
+TEST_F(ExpTest, Float_P)
+{
+ test_kernel::TestDataFloatExp test_data_kernel;
+ std::vector<float> output_data_vector = checkExpKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+ test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(ExpTest, Input_output_type_mismatch_NEG)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- Shape input_shape{1, 1, 7};
- std::vector<float> input_data{0.0f, 1.0f, -1.0f, 100.0f, -100.0f, 0.01f, -0.01f};
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- Exp kernel(&input_tensor, &output_tensor);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- std::vector<int32_t> ref_output_shape{1, 1, 7};
- std::vector<float> ref_output_data{std::exp(0.0f), std::exp(1.0f), std::exp(-1.0f),
- std::exp(100.0f), std::exp(-100.0f), std::exp(0.01f),
- std::exp(-0.01f)};
- EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+ test_kernel::NegTestDataInputOutputTypeMismatchExpKernel test_data_kernel;
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/ExpandDims.cpp b/onert-micro/luci-interpreter/src/kernels/ExpandDims.cpp
index 867af01bb..1035bb8f4 100644
--- a/onert-micro/luci-interpreter/src/kernels/ExpandDims.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/ExpandDims.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,6 +40,7 @@ void configure_kernel_CircleExpandDims(const circle::Operator *cur_op,
assert(output != nullptr);
auto axis_data = runtime_graph->getConstDataByTensor(axis);
+ assert(axis_data != nullptr);
int32_t axis_value;
@@ -65,7 +65,7 @@ void configure_kernel_CircleExpandDims(const circle::Operator *cur_op,
}
void execute_kernel_CircleExpandDims(const circle::Operator *cur_op,
- BaseRuntimeGraph *runtime_graph, bool is_inplace)
+ BaseRuntimeGraph *runtime_graph)
{
const auto input_index = cur_op->inputs()->operator[](0);
const auto output_index = cur_op->outputs()->operator[](0);
@@ -76,6 +76,8 @@ void execute_kernel_CircleExpandDims(const circle::Operator *cur_op,
const auto input = runtime_graph->getCircleTensorByIndex(input_index);
const auto output = runtime_graph->getCircleTensorByIndex(output_index);
+ bool is_inplace = runtime_graph->is_inplace_op(cur_op);
+
if (is_inplace)
{
runtime_graph->makeInplaceOperation(input, output);
diff --git a/onert-micro/luci-interpreter/src/kernels/ExpandDims.test.cpp b/onert-micro/luci-interpreter/src/kernels/ExpandDims.test.cpp
index 1ebbcd804..b7448cd8b 100644
--- a/onert-micro/luci-interpreter/src/kernels/ExpandDims.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/ExpandDims.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,16 +14,13 @@
* limitations under the License.
*/
-// TODO enable it
-#if 0
-#include "kernels/ExpandDims.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/expand_dims/ExpandDimsKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
@@ -32,87 +28,59 @@ using namespace testing;
class ExpandDimsTest : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-TEST_F(ExpandDimsTest, PositiveAxis)
+template <typename T>
+std::vector<T> checkExpandDimsKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- std::vector<int32_t> input_data{-1, 1, -2, 2};
- std::initializer_list<int32_t> input_shape = {2, 2};
-
- std::initializer_list<int32_t> axis_value = {0};
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- Tensor input_tensor =
- makeInputTensor<DataType::S32>(input_shape, input_data, _memory_manager.get());
- Tensor axis_tensor = makeInputTensor<DataType::S32>({1}, axis_value, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S32);
-
- ExpandDims kernel(&input_tensor, &axis_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<int32_t>(output_tensor), ::testing::ElementsAreArray(input_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 2}));
-}
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
-TEST_F(ExpandDimsTest, NegAxis)
-{
- std::vector<int32_t> input_data{-1, 1, -2, 2};
- std::initializer_list<int32_t> input_shape = {2, 2};
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
- std::initializer_list<int32_t> axis_value = {-1};
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
- Tensor input_tensor =
- makeInputTensor<DataType::S32>(input_shape, input_data, _memory_manager.get());
- Tensor axis_tensor = makeInputTensor<DataType::S32>({1}, axis_value, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S32);
+ runtime_module.execute();
- ExpandDims kernel(&input_tensor, &axis_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
- EXPECT_THAT(extractTensorData<int32_t>(output_tensor), ::testing::ElementsAreArray(input_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({2, 2, 1}));
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST_F(ExpandDimsTest, InvalidAxisType_NEG)
+TEST_F(ExpandDimsTest, MainTest_P)
{
- std::vector<int32_t> input_data{-1, 1, -2, 2};
- std::initializer_list<int32_t> input_shape = {2, 2};
-
- std::initializer_list<float> axis_value = {1.0};
-
- Tensor input_tensor =
- makeInputTensor<DataType::S32>(input_shape, input_data, _memory_manager.get());
- Tensor axis_tensor = makeInputTensor<DataType::FLOAT32>({1}, axis_value, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S32);
-
- ExpandDims kernel(&input_tensor, &axis_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::TestDataExpandDimsKernel<float> test_data_kernel;
+ std::vector<float> output_data_vector = checkExpandDimsKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-TEST_F(ExpandDimsTest, InvalidAxisValue_NEG)
+TEST_F(ExpandDimsTest, WrongAxisType_NEG)
{
- std::vector<int32_t> input_data{-1, 1, -2, 2};
- std::initializer_list<int32_t> input_shape = {2, 2};
-
- std::initializer_list<int32_t> axis_value = {3};
-
- Tensor input_tensor =
- makeInputTensor<DataType::S32>(input_shape, input_data, _memory_manager.get());
- Tensor axis_tensor = makeInputTensor<DataType::S32>({1}, axis_value, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S32);
-
- ExpandDims kernel(&input_tensor, &axis_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::NegTestDataInvalidInputTypeExpandDimsKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
-#endif
diff --git a/onert-micro/luci-interpreter/src/kernels/Fill.cpp b/onert-micro/luci-interpreter/src/kernels/Fill.cpp
index 6707c7061..8bc501463 100644
--- a/onert-micro/luci-interpreter/src/kernels/Fill.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Fill.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright 2020 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,103 +15,70 @@
* limitations under the License.
*/
-#include "kernels/Fill.h"
+#include "Builders.h"
+#include "TISOKernel.h"
#include "kernels/Utils.h"
-#include "PALFill.h"
namespace luci_interpreter
{
-namespace kernels
+namespace
{
-Fill::Fill(const Tensor *dims, const Tensor *value, Tensor *output)
- : Kernel({dims, value}, {output})
+template <typename T> void fillImpl(const size_t flat_size, const T *value_data, T *output_data)
{
-}
-
-template <typename T> void Fill::configureShape()
-{
- const auto dims_data = getTensorData<T>(dims());
- Shape output_shape(dims()->shape().dim(0));
-
- for (int i = 0; i < output_shape.num_dims(); ++i)
+ for (int i = 0; i < flat_size; ++i)
{
- T data = dims_data[i];
- if (data < 0)
- assert(false && "Fill dimensions must be >= 0");
-
- output_shape.dim(i) = data;
+ output_data[i] = *value_data;
}
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(output_shape);
}
-void Fill::configure()
+} // namespace
+
+void configure_kernel_CircleFill(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- const auto dims_shape = dims()->shape();
- const auto value_shape = value()->shape();
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
+ // value tensor must be a scalar or has one element
+ LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.input2()) == 0 or
+ Tensor::num_elements(kernel.input2()) == 1);
+ // value and output type must match
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input2()) ==
+ Tensor::element_type(kernel.output()));
+}
- // Make sure the 1st input tensor is 1-D
- LUCI_INTERPRETER_CHECK(dims_shape.num_dims() == 1);
+void execute_kernel_CircleFill(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
- // Make sure the 1st input tensor is int32 or int64
- LUCI_INTERPRETER_CHECK(dims()->element_type() == DataType::S32 or
- dims()->element_type() == DataType::S64);
+ const circle::Tensor *value = kernel.input2();
+ const circle::Tensor *output = kernel.output();
- // Make sure the 2nd input tensor is a scalar
- LUCI_INTERPRETER_CHECK(value_shape.num_dims() == 0)
+ kernels::TISOData tiso_data = kernel.readData();
+ const uint8_t *value_data = tiso_data.input2_data;
+ uint8_t *output_data = tiso_data.output_data;
- // Check zero point and scale for S16 and S8
- if (value()->element_type() == DataType::S16 or value()->element_type() == DataType::S8)
- {
- LUCI_INTERPRETER_CHECK(value()->scale() == output()->scale());
- LUCI_INTERPRETER_CHECK(value()->zero_point() == output()->zero_point());
+ const size_t flat_size = Tensor::num_elements(output);
- if (value()->element_type() == DataType::S16)
- LUCI_INTERPRETER_CHECK(value()->zero_point() == 0);
- }
- // Resize output
- switch (dims()->element_type())
+ switch (Tensor::element_type(value))
{
- case DataType::S32:
- configureShape<int32_t>();
- break;
- case DataType::S64:
- configureShape<int64_t>();
- break;
- default:
- assert(false && "Unsupported type.");
- }
-}
-
-void Fill::execute() const
-{
- switch (output()->element_type())
- {
- case DataType::S8:
- tflite::reference_ops::Fill(getTensorShape(value()), getTensorData<int8_t>(value()),
- getTensorShape(output()), getTensorData<int8_t>(output()));
- break;
- case DataType::S16:
- tflite::reference_ops::Fill(getTensorShape(value()), getTensorData<int16_t>(value()),
- getTensorShape(output()), getTensorData<int16_t>(output()));
+#ifndef DIS_FLOAT
+ case DataType::FLOAT32:
+ fillImpl<float>(flat_size, kernels::getTensorData<float>(value_data),
+ kernels::getTensorData<float>(output_data));
break;
+#endif // DIS_FLOAT
case DataType::S32:
- tflite::reference_ops::Fill(getTensorShape(value()), getTensorData<int32_t>(value()),
- getTensorShape(output()), getTensorData<int32_t>(output()));
+ fillImpl<int32_t>(flat_size, kernels::getTensorData<int32_t>(value_data),
+ kernels::getTensorData<int32_t>(output_data));
break;
- case DataType::S64:
- tflite::reference_ops::Fill(getTensorShape(value()), getTensorData<int64_t>(value()),
- getTensorShape(output()), getTensorData<int64_t>(output()));
- break;
- case DataType::FLOAT32:
- tflite::reference_ops::Fill(getTensorShape(value()), getTensorData<float>(value()),
- getTensorShape(output()), getTensorData<float>(output()));
+#ifndef DIS_QUANT
+ case DataType::U8:
+ fillImpl<uint8_t>(flat_size, kernels::getTensorData<uint8_t>(value_data),
+ kernels::getTensorData<uint8_t>(output_data));
break;
+#endif // DIS_QUANT
default:
- assert(false && "Unsupported type.");
+ assert(false && "Not impl yet");
}
}
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Fill.h b/onert-micro/luci-interpreter/src/kernels/Fill.h
deleted file mode 100644
index 4e517c5d8..000000000
--- a/onert-micro/luci-interpreter/src/kernels/Fill.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_FILL_H
-#define LUCI_INTERPRETER_KERNELS_FILL_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Fill : public Kernel
-{
-public:
- Fill(const Tensor *dims, const Tensor *value, Tensor *output);
-
- const Tensor *dims() const { return _inputs[0]; }
- const Tensor *value() const { return _inputs[1]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-
-private:
- template <typename T> void configureShape();
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_FILL_H
diff --git a/onert-micro/luci-interpreter/src/kernels/Fill.test.cpp b/onert-micro/luci-interpreter/src/kernels/Fill.test.cpp
index 4033caa45..a95c7a35f 100644
--- a/onert-micro/luci-interpreter/src/kernels/Fill.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Fill.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,14 +14,14 @@
* limitations under the License.
*/
-#include "kernels/Fill.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/fill/FillKernel.h"
+#include "luci_interpreter/test_models/fill/NegFillKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
@@ -30,141 +29,69 @@ using namespace testing;
class FillTest : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-template <typename T, DataType DT> void runFillIntKernel(IMemoryManager *memory_manager)
+template <typename T> std::vector<T> checkFillKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- Shape dims_shape{2};
-
- std::vector<int32_t> dims_data = {2, 3};
- std::vector<T> value_data = {5};
-
- Tensor dims = makeInputTensor<loco::DataType::S32>(dims_shape, dims_data, memory_manager);
- Tensor value = makeInputTensor<DT>(/*scalar*/ {}, value_data, memory_manager);
-
- Tensor output_tensor = makeOutputTensor(DT);
-
- Fill kernel(&dims, &value, &output_tensor);
-
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- std::vector<T> ref_output_data{5, 5, 5, 5, 5, 5};
- EXPECT_THAT(extractTensorData<T>(output_tensor), ref_output_data);
-
- std::vector<int32_t> ref_output_shape{2, 3};
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
-}
-
-template <DataType DT> void runFillQuantIntKernel(IMemoryManager *memory_manager)
-{
- Shape dims_shape{2};
-
- std::vector<int32_t> dims_data = {2, 3};
- std::vector<float> value_data = {5};
-
- int32_t zero_point = 0;
-
- if (DT == loco::DataType::S8)
- zero_point = 1;
-
- Tensor dims = makeInputTensor<loco::DataType::S32>(dims_shape, dims_data, memory_manager);
- Tensor value = makeInputTensor<DT>(/*scalar*/ {}, /*scale*/ 0.25, /*zero_point*/ zero_point,
- value_data, memory_manager);
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- Tensor output_tensor = makeOutputTensor(DT, /*scale*/ 0.25, /*zero_point*/ zero_point);
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- Fill kernel(&dims, &value, &output_tensor);
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
- std::vector<float> ref_output_data{5, 5, 5, 5, 5, 5};
- EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
+ runtime_module.execute();
- std::vector<int32_t> ref_output_shape{2, 3};
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
-}
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
-TEST_F(FillTest, FillInt)
-{
- // Run for int32_t input
- runFillIntKernel<int32_t, loco::DataType::S32>(_memory_manager.get());
- // Run for int64_t input
- runFillIntKernel<int64_t, loco::DataType::S64>(_memory_manager.get());
- // Run for int8_t input
- runFillQuantIntKernel<loco::DataType::S8>(_memory_manager.get());
- // Run for int16_t input
- runFillQuantIntKernel<loco::DataType::S16>(_memory_manager.get());
-
- SUCCEED();
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST_F(FillTest, FillFloat)
+TEST_F(FillTest, MainTest_P)
{
- Shape dims_shape{3};
-
- std::vector<int64_t> dims_data = {2, 2, 2};
- std::vector<float> value_data = {5};
-
- Tensor dims = makeInputTensor<loco::DataType::S64>(dims_shape, dims_data, _memory_manager.get());
- Tensor value =
- makeInputTensor<loco::DataType::FLOAT32>(/*scalar*/ {}, value_data, _memory_manager.get());
-
- Tensor output_tensor = makeOutputTensor(loco::DataType::FLOAT32);
-
- Fill kernel(&dims, &value, &output_tensor);
-
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- std::vector<float> ref_output_data{5, 5, 5, 5, 5, 5, 5, 5};
-
- std::vector<int32_t> ref_output_shape{2, 2, 2};
- EXPECT_THAT(extractTensorData<float>(output_tensor), ref_output_data);
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+ test_kernel::TestDataFillKernel<float> test_data_kernel;
+ std::vector<float> output_data_vector = checkFillKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-TEST_F(FillTest, Invalid_Input_Shape_NEG)
+TEST_F(FillTest, Input_output_type_mismatch_NEG)
{
- Shape dims_shape{1, 3};
-
- std::vector<int32_t> dims_data = {2, 2, 2};
- std::vector<float> value_data = {5};
-
- Tensor dims = makeInputTensor<loco::DataType::S32>(dims_shape, dims_data, _memory_manager.get());
- Tensor value =
- makeInputTensor<loco::DataType::FLOAT32>(/*scalar*/ {}, value_data, _memory_manager.get());
-
- Tensor output_tensor = makeOutputTensor(loco::DataType::FLOAT32);
-
- Fill kernel(&dims, &value, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::NegTestDataInputTypeMismatchFillKernel test_data_kernel;
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST_F(FillTest, Invalid_Value_Shape_NEG)
+TEST_F(FillTest, Wrong_input_shape_NEG)
{
- Shape dims_shape{3};
-
- std::vector<int32_t> dims_data = {2, 2, 2};
- std::vector<float> value_data = {5};
-
- Tensor dims = makeInputTensor<loco::DataType::S32>(dims_shape, dims_data, _memory_manager.get());
- Tensor value = makeInputTensor<loco::DataType::FLOAT32>({1}, value_data, _memory_manager.get());
-
- Tensor output_tensor = makeOutputTensor(loco::DataType::FLOAT32);
-
- Fill kernel(&dims, &value, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::NegTestDataWrongInputShapeFillKernel test_data_kernel;
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Floor.h b/onert-micro/luci-interpreter/src/kernels/Floor.h
index 47d112455..ca3ad5997 100644
--- a/onert-micro/luci-interpreter/src/kernels/Floor.h
+++ b/onert-micro/luci-interpreter/src/kernels/Floor.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Floor.test.cpp b/onert-micro/luci-interpreter/src/kernels/Floor.test.cpp
index 37523be2d..30076fb54 100644
--- a/onert-micro/luci-interpreter/src/kernels/Floor.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Floor.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/FloorDiv.h b/onert-micro/luci-interpreter/src/kernels/FloorDiv.h
index 7a0d6b1e0..e9c47d81a 100644
--- a/onert-micro/luci-interpreter/src/kernels/FloorDiv.h
+++ b/onert-micro/luci-interpreter/src/kernels/FloorDiv.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/FullyConnected.cpp b/onert-micro/luci-interpreter/src/kernels/FullyConnected.cpp
index 2cfdc8431..0493eaa47 100644
--- a/onert-micro/luci-interpreter/src/kernels/FullyConnected.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/FullyConnected.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,10 +33,9 @@ void evalFloat(const circle::Tensor *input, const circle::Tensor *weights,
kernels::calculateActivationRange(luci_actfunc(options->fused_activation_function()),
&activation_min, &activation_max);
- tflite::FullyConnectedParams params{};
+ luci_interpreter_pal::FullyConnectedParams params{};
params.float_activation_min = activation_min;
params.float_activation_max = activation_max;
- params.weights_format = tflite::FullyConnectedWeightsFormat::kDefault;
auto *input_data = runtime_graph->getDataByTensor(input);
auto *output_data = runtime_graph->getDataByTensor(output);
@@ -49,11 +47,19 @@ void evalFloat(const circle::Tensor *input, const circle::Tensor *weights,
assert(weights_data != nullptr);
assert(output_data != nullptr);
- tflite::reference_ops::FullyConnected(
- params, kernels::getTensorShape(input), kernels::getTensorData<float>(input_data),
- kernels::getTensorShape(weights), kernels::getTensorData<float>(weights_data),
- kernels::getTensorShape(bias), kernels::getTensorData<float>(bias_data),
- kernels::getTensorShape(output), kernels::getTensorData<float>(output_data));
+ int32_t input_shape[kMaxSmallSize];
+ kernels::getTensorDims(input, runtime_graph, input_shape);
+
+ int32_t weight_shape[kMaxSmallSize];
+ kernels::getTensorDims(weights, runtime_graph, weight_shape);
+
+ int32_t output_shape[kMaxSmallSize];
+ kernels::getTensorDims(output, runtime_graph, output_shape);
+
+ luci_interpreter_pal::FullyConnected(
+ params, input_shape, kernels::getTensorData<float>(input_data), weight_shape,
+ kernels::getTensorData<float>(weights_data), kernels::getTensorData<float>(bias_data),
+ output_shape, kernels::getTensorData<float>(output_data));
}
#ifndef DIS_QUANT
@@ -77,7 +83,7 @@ void evalQuantized(const circle::Tensor *input, const circle::Tensor *weights,
int32_t filter_offset = -Tensor::zero_point(weights);
int32_t output_offset = Tensor::zero_point(output);
- tflite::FullyConnectedParams op_params{};
+ luci_interpreter_pal::FullyConnectedParams op_params{};
op_params.input_offset = input_offset;
op_params.weights_offset = filter_offset;
op_params.output_offset = output_offset;
@@ -98,65 +104,24 @@ void evalQuantized(const circle::Tensor *input, const circle::Tensor *weights,
assert(weights_data != nullptr);
assert(output_data != nullptr);
- tflite::reference_ops::FullyConnected(
- op_params, kernels::getTensorShape(input), kernels::getTensorData<uint8_t>(input_data),
- kernels::getTensorShape(weights), kernels::getTensorData<uint8_t>(weights_data),
- kernels::getTensorShape(bias), kernels::getTensorData<int32_t>(bias_data),
- kernels::getTensorShape(output), kernels::getTensorData<uint8_t>(output_data));
-}
-
-void evalQuantizedS8(const circle::Tensor *input, const circle::Tensor *weights,
- const circle::Tensor *bias, const circle::Tensor *output,
- const circle::FullyConnectedOptions *options, BaseRuntimeGraph *runtime_graph)
-{
- double real_multiplier = 0.0;
- int output_shift;
- int32_t output_activation_min;
- int32_t output_activation_max;
- int32_t output_multiplier;
- real_multiplier = kernels::getQuantizedConvolutionMultipler(
- Tensor::scale(input), Tensor::scale(weights), Tensor::scale(output));
- kernels::quantizeMultiplier(real_multiplier, &output_multiplier, &output_shift);
- kernels::calculateActivationRangeQuantized(luci_actfunc(options->fused_activation_function()),
- output, &output_activation_min,
- &output_activation_max);
-
- int32_t input_offset = -Tensor::zero_point(input);
- int32_t filter_offset = -Tensor::zero_point(weights);
- int32_t output_offset = Tensor::zero_point(output);
-
- tflite::FullyConnectedParams op_params{};
- op_params.input_offset = input_offset;
- op_params.weights_offset = filter_offset;
- op_params.output_offset = output_offset;
- op_params.output_multiplier = output_multiplier;
- op_params.output_shift = output_shift;
- op_params.quantized_activation_min = output_activation_min;
- op_params.quantized_activation_max = output_activation_max;
- op_params.lhs_cacheable = false;
- op_params.rhs_cacheable = false;
+ int32_t input_shape[kMaxSmallSize];
+ kernels::getTensorDims(input, runtime_graph, input_shape);
- auto *input_data = runtime_graph->getDataByTensor(input);
- auto *output_data = runtime_graph->getDataByTensor(output);
+ int32_t weights_shape[kMaxSmallSize];
+ kernels::getTensorDims(weights, runtime_graph, weights_shape);
- auto *weights_data = runtime_graph->getConstDataByTensor(weights);
- auto *bias_data = runtime_graph->getConstDataByTensor(bias);
-
- assert(input_data != nullptr);
- assert(weights_data != nullptr);
- assert(output_data != nullptr);
+ int32_t output_shape[kMaxSmallSize];
+ kernels::getTensorDims(output, runtime_graph, output_shape);
- luci_interpreter_pal::FullyConnected<int8_t>(
- op_params, kernels::getTensorShape(input), kernels::getTensorData<int8_t>(input_data),
- kernels::getTensorShape(weights), kernels::getTensorData<int8_t>(weights_data),
- kernels::getTensorShape(bias), kernels::getTensorData<int32_t>(bias_data),
- kernels::getTensorShape(output), kernels::getTensorData<int8_t>(output_data));
+ luci_interpreter_pal::FullyConnected(
+ op_params, input_shape, kernels::getTensorData<uint8_t>(input_data), weights_shape,
+ kernels::getTensorData<uint8_t>(weights_data), kernels::getTensorData<int32_t>(bias_data),
+ output_shape, kernels::getTensorData<uint8_t>(output_data));
}
#endif
} // namespace
-// TODO think how remove unused param
void configure_kernel_CircleFullyConnected(const circle::Operator *cur_op,
BaseRuntimeGraph *runtime_graph)
{
@@ -207,7 +172,11 @@ void configure_kernel_CircleFullyConnected(const circle::Operator *cur_op,
LUCI_INTERPRETER_CHECK(Tensor::num_dims(weights) == 2);
LUCI_INTERPRETER_CHECK(bias == nullptr || Tensor::num_elements(bias) == Tensor::dim(weights, 0));
- LUCI_INTERPRETER_CHECK(Tensor::num_elements(input) % Tensor::dim(weights, 1) == 0);
+
+#ifdef DIS_DYN_SHAPES
+ int32_t input_num_elements = Tensor::num_elements(input);
+ LUCI_INTERPRETER_CHECK(input_num_elements % Tensor::dim(weights, 1) == 0);
+#endif // DIS_DYN_SHAPES
if (bias)
LUCI_INTERPRETER_CHECK(Tensor::num_elements(bias) == Tensor::dim(weights, 0));
@@ -220,7 +189,7 @@ void configure_kernel_CircleFullyConnected(const circle::Operator *cur_op,
// TODO think how remove unused param
void execute_kernel_CircleFullyConnected(const circle::Operator *cur_op,
- BaseRuntimeGraph *runtime_graph, bool)
+ BaseRuntimeGraph *runtime_graph)
{
const auto input_index = cur_op->inputs()->operator[](0);
const auto weight_index = cur_op->inputs()->operator[](1);
@@ -248,9 +217,6 @@ void execute_kernel_CircleFullyConnected(const circle::Operator *cur_op,
case DataType::U8:
evalQuantized(input, weights, bias, output, options, runtime_graph);
break;
- case DataType::S8:
- evalQuantizedS8(input, weights, bias, output, options, runtime_graph);
- break;
#endif // DIS_QUANT
#ifndef DIS_FLOAT
case DataType::FLOAT32:
diff --git a/onert-micro/luci-interpreter/src/kernels/FullyConnected.test.cpp b/onert-micro/luci-interpreter/src/kernels/FullyConnected.test.cpp
index feda0d83d..cbccd5d4f 100644
--- a/onert-micro/luci-interpreter/src/kernels/FullyConnected.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/FullyConnected.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,250 +13,112 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-// TODO enable it
-#if 0
-#include "kernels/FullyConnected.h"
+
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/fully_connected/FloatFullyConnectedKernel.h"
+#include "luci_interpreter/test_models/fully_connected/U8FullyConnectedKernel.h"
+#include "luci_interpreter/test_models/fully_connected/NegFullyConnectedKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
using namespace testing;
-template <typename T>
-void Check(std::initializer_list<int32_t> input_shape, std::initializer_list<int32_t> weights_shape,
- std::initializer_list<int32_t> bias_shape, std::initializer_list<int32_t> output_shape,
- std::initializer_list<float> input_data, std::initializer_list<float> weights_data,
- std::initializer_list<float> bias_data, std::initializer_list<float> output_data)
+class FullyConnectedTest : public ::testing::Test
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
- Tensor weights_tensor =
- makeInputTensor<DataType::FLOAT32>(weights_shape, weights_data, memory_manager.get());
- Tensor bias_tensor =
- makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- FullyConnectedParams params{};
- params.activation = Activation::RELU;
-
- FullyConnected kernel(&input_tensor, &weights_tensor, &bias_tensor, &output_tensor, params);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
- EXPECT_THAT(extractTensorData<T>(output_tensor), FloatArrayNear(output_data));
-}
+ // Do nothing
+};
-template <>
-void Check<int8_t>(std::initializer_list<int32_t> input_shape,
- std::initializer_list<int32_t> weights_shape,
- std::initializer_list<int32_t> bias_shape,
- std::initializer_list<int32_t> output_shape,
- std::initializer_list<float> input_data,
- std::initializer_list<float> weights_data,
- std::initializer_list<float> bias_data, std::initializer_list<float> output_data)
+template <typename T>
+std::vector<T> checkFullyConnectedKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- const float quantized_tolerance = getTolerance(-127, 128, 255);
- std::pair<float, int32_t> input_quant_param = quantizationParams<int8_t>(-63.5, 64);
- std::pair<float, int32_t> output_quant_param = quantizationParams<int8_t>(-127, 128);
- Tensor input_tensor =
- makeInputTensor<DataType::S8>(input_shape, input_quant_param.first, input_quant_param.second,
- input_data, memory_manager.get());
- Tensor weights_tensor =
- makeInputTensor<DataType::S8>(weights_shape, input_quant_param.first, input_quant_param.second,
- weights_data, memory_manager.get());
- Tensor bias_tensor =
- makeInputTensor<DataType::S32>(bias_shape, input_quant_param.first * input_quant_param.first, 0,
- bias_data, memory_manager.get());
- Tensor output_tensor =
- makeOutputTensor(DataType::S8, output_quant_param.first, output_quant_param.second);
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- FullyConnectedParams params{};
- params.activation = Activation::RELU;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- FullyConnected kernel(&input_tensor, &weights_tensor, &bias_tensor, &output_tensor, params);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
- EXPECT_THAT(dequantizeTensorData(output_tensor),
- FloatArrayNear(output_data, quantized_tolerance));
-}
+ // set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
-template <>
-void Check<uint8_t>(
- std::initializer_list<int32_t> input_shape, std::initializer_list<int32_t> weights_shape,
- std::initializer_list<int32_t> bias_shape, std::initializer_list<int32_t> output_shape,
- std::initializer_list<float> input_data, std::initializer_list<float> weights_data,
- std::initializer_list<float> bias_data, std::initializer_list<float> output_data)
-{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- const float quantized_tolerance = getTolerance(-127, 128, 255);
- std::pair<float, int32_t> input_quant_param = quantizationParams<uint8_t>(-63.5, 64);
- std::pair<float, int32_t> output_quant_param = quantizationParams<uint8_t>(-127, 128);
- Tensor input_tensor =
- makeInputTensor<DataType::U8>(input_shape, input_quant_param.first, input_quant_param.second,
- input_data, memory_manager.get());
- Tensor weights_tensor =
- makeInputTensor<DataType::U8>(weights_shape, input_quant_param.first, input_quant_param.second,
- weights_data, memory_manager.get());
- Tensor bias_tensor =
- makeInputTensor<DataType::S32>(bias_shape, input_quant_param.first * input_quant_param.first, 0,
- bias_data, memory_manager.get());
- Tensor output_tensor =
- makeOutputTensor(DataType::U8, output_quant_param.first, output_quant_param.second);
+ runtime_module.execute();
- FullyConnectedParams params{};
- params.activation = Activation::RELU;
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
- FullyConnected kernel(&input_tensor, &weights_tensor, &bias_tensor, &output_tensor, params);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
- EXPECT_THAT(dequantizeTensorData(output_tensor),
- FloatArrayNear(output_data, quantized_tolerance));
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-template <typename T> class FullyConnectedTest : public ::testing::Test
+TEST_F(FullyConnectedTest, Float_P)
{
-};
-
-using DataTypes = ::testing::Types<float, uint8_t, int8_t>;
-TYPED_TEST_SUITE(FullyConnectedTest, DataTypes);
+ test_kernel::TestDataFloatFullyConnected test_data_kernel;
+ std::vector<float> output_data_vector = checkFullyConnectedKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+ test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
-TYPED_TEST(FullyConnectedTest, Simple)
+TEST_F(FullyConnectedTest, U8_P)
{
- Check<TypeParam>({3, 2, 2, 1}, {3, 6}, {3}, {2, 3},
- {
- -3, -5, 5, 4, 9, -2, // batch = 0
- -3, -2, -4, 9, -8, 1, // batch = 1
- },
- {
- -3, -7, 4, -4, -6, 4, // unit = 0
- 3, 5, 2, 3, -3, -8, // unit = 1
- -3, 7, 4, 9, 0, -5, // unit = 2
- },
- {-1, -5, -8},
- {
- 0, 0, 32, // batch = 0
- 22, 11, 47, // batch = 1
- });
+ test_kernel::TestDataU8FullyConnected test_data_kernel;
+ std::vector<uint8_t> output_data_vector = checkFullyConnectedKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-TEST(FullyConnectedTest, InvalidBiasType_NEG)
+TEST_F(FullyConnectedTest, Wrong_weight_type_NEG)
{
- Shape input_shape{3, 2, 2, 1};
- std::vector<float> input_data{
- -3, -5, 5, 4, 9, -2, // batch = 0
- -3, -2, -4, 9, -8, 1, // batch = 1
- };
- Shape weights_shape{3, 6};
- std::vector<float> weights_data{
- -3, -7, 4, -4, -6, 4, // unit = 0
- 3, 5, 2, 3, -3, -8, // unit = 1
- -3, 7, 4, 9, 0, -5, // unit = 2
- };
- Shape bias_shape{3};
- std::vector<int32_t> bias_data{-1, -5, -8};
-
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
- Tensor weights_tensor =
- makeInputTensor<DataType::FLOAT32>(weights_shape, weights_data, memory_manager.get());
- Tensor bias_tensor = makeInputTensor<DataType::S32>(bias_shape, bias_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- FullyConnectedParams params{};
- params.activation = Activation::RELU;
-
- FullyConnected kernel(&input_tensor, &weights_tensor, &bias_tensor, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::NegTestDataWrongWeightTypeFullyConnectedKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST(FullyConnectedTest, InvalidWeightShapeDim_NEG)
+TEST_F(FullyConnectedTest, Wrong_weight_shape_NEG)
{
- Shape input_shape{3, 2, 2, 1};
- std::vector<float> input_data{
- -3, -5, 5, 4, 9, -2, // batch = 0
- -3, -2, -4, 9, -8, 1, // batch = 1
- };
- Shape weights_shape{1, 3, 6};
- std::vector<float> weights_data{
- -3, -7, 4, -4, -6, 4, // unit = 0
- 3, 5, 2, 3, -3, -8, // unit = 1
- -3, 7, 4, 9, 0, -5, // unit = 2
- };
- Shape bias_shape{3};
- std::vector<float> bias_data{-1, -5, -8};
-
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
- Tensor weights_tensor =
- makeInputTensor<DataType::FLOAT32>(weights_shape, weights_data, memory_manager.get());
- Tensor bias_tensor =
- makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- FullyConnectedParams params{};
- params.activation = Activation::RELU;
-
- FullyConnected kernel(&input_tensor, &weights_tensor, &bias_tensor, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::NegTestDataWrongWeightShapeFullyConnectedKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST(FullyConnectedTest, BiasElementNumWeightDimMismatch_NEG)
+TEST_F(FullyConnectedTest, Wrong_bias_shape_NEG)
{
- Shape input_shape{3, 2, 2, 1};
- std::vector<float> input_data{
- -3, -5, 5, 4, 9, -2, // batch = 0
- -3, -2, -4, 9, -8, 1, // batch = 1
- };
- Shape weights_shape{6, 3};
- std::vector<float> weights_data{
- -3, -7, 4, // unit = 0
- -4, -6, 4, // unit = 1
- 3, 5, 2, // unit = 2
- 3, -3, -8, // unit = 3
- -3, 7, 4, // unit = 4
- 9, 0, -5, // unit = 5
- };
- Shape bias_shape{3};
- std::vector<float> bias_data{-1, -5, -8};
-
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
- Tensor weights_tensor =
- makeInputTensor<DataType::FLOAT32>(weights_shape, weights_data, memory_manager.get());
- Tensor bias_tensor =
- makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- FullyConnectedParams params{};
- params.activation = Activation::RELU;
-
- FullyConnected kernel(&input_tensor, &weights_tensor, &bias_tensor, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::NegTestDataWrongBiasShapeFullyConnectedKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
+// TODO: add tests for S8
+
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
-#endif
diff --git a/onert-micro/luci-interpreter/src/kernels/Gather.cpp b/onert-micro/luci-interpreter/src/kernels/Gather.cpp
index d26b718f1..b146b8993 100644
--- a/onert-micro/luci-interpreter/src/kernels/Gather.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Gather.cpp
@@ -15,125 +15,146 @@
* limitations under the License.
*/
-#include "kernels/Gather.h"
+#include "Builders.h"
#include "kernels/Utils.h"
-#include "PALGather.h"
+#include "TISOKernel.h"
#include <cassert>
namespace luci_interpreter
{
-
-namespace kernels
+namespace
{
-Gather::Gather(const Tensor *params, const Tensor *indices, Tensor *output,
- const GatherParams &gparams)
- : KernelWithParams<GatherParams>({params, indices}, {output}, gparams)
+template <typename InputT, typename CoordsT = int32_t>
+void gather(const circle::GatherOptions *options, kernels::TISOKernel *kernel)
{
-}
-
-void Gather::configure()
-{
- if (params()->element_type() == DataType::FLOAT32)
- {
- LUCI_INTERPRETER_CHECK(output()->element_type() == DataType::FLOAT32);
- }
- else
- {
- assert(false && "Unsupported type.");
- }
-
- LUCI_INTERPRETER_CHECK(indices()->element_type() == DataType::S32 ||
- indices()->element_type() == DataType::S64);
+ kernels::TISOData tiso_data = kernel->readData();
- // refer tensorflow/lite/kernels/gather.cc
+ const InputT *input_data = kernels::getTensorData<InputT>(tiso_data.input1_data);
+ const CoordsT *coords_data = kernels::getTensorData<CoordsT>(tiso_data.input2_data);
+ InputT *output_data = kernels::getTensorData<InputT>(tiso_data.output_data);
- const Shape &params_shape = params()->shape();
- const Shape &indices_shape = indices()->shape();
+ const circle::Tensor *input = kernel->input1();
+ const circle::Tensor *coords = kernel->input2();
- int axis = _params.axis;
+ const int input_dims_size = Tensor::num_dims(input);
+ int axis = options->axis();
if (axis < 0)
{
- axis += params_shape.num_dims();
+ axis += input_dims_size;
}
- LUCI_INTERPRETER_CHECK(0 <= axis && axis < params_shape.num_dims());
- int batch_dims = _params.batch_dims;
- // batch_dims should be in range: [-rank(indices), rank(indices)].
- // Negative batch_dims is added with rank of positions.
+ int batch_dims = options->batch_dims();
+ // batch_dims should be in range: [-rank(coords), rank(coords)].
+ // Negative batch_dims is added with rank of coords.
+ const int coords_dims_size = Tensor::num_dims(coords);
if (batch_dims < 0)
{
- batch_dims += indices_shape.num_dims();
+ batch_dims += coords_dims_size;
}
- LUCI_INTERPRETER_CHECK(batch_dims <= axis);
- LUCI_INTERPRETER_CHECK(0 <= batch_dims && batch_dims < params_shape.num_dims());
- LUCI_INTERPRETER_CHECK(batch_dims <= indices_shape.num_dims());
+
+ const int axis_size = Tensor::dim(input, axis);
+
+ int batch_size = 1;
for (int i = 0; i < batch_dims; ++i)
{
- LUCI_INTERPRETER_CHECK(params_shape.dim(i) == indices_shape.dim(i));
+ batch_size *= Tensor::dim(input, i);
}
-
- const int num_dimensions = params_shape.num_dims() + indices_shape.num_dims() - 1 - batch_dims;
-
- Shape output_shape(num_dimensions);
- int output_index = 0;
- for (int i = 0; i < axis; ++i)
+ int outer_size = 1;
+ for (int i = batch_dims; i < axis; ++i)
{
- output_shape.dim(output_index++) = params_shape.dim(i);
+ outer_size *= Tensor::dim(input, i);
}
- for (int i = batch_dims; i < indices_shape.num_dims(); ++i)
+ int inner_size = 1;
+ for (int i = axis + 1; i < input_dims_size; ++i)
{
- output_shape.dim(output_index++) = indices_shape.dim(i);
+ inner_size *= Tensor::dim(input, i);
}
- for (int i = axis + 1; i < params_shape.num_dims(); ++i)
+ int coord_size = 1;
+ for (int i = batch_dims; i < coords_dims_size; ++i)
{
- output_shape.dim(output_index++) = params_shape.dim(i);
+ coord_size *= Tensor::dim(coords, i);
}
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(output_shape);
-}
-void Gather::execute() const
-{
- switch (params()->element_type())
+ for (int batch = 0; batch < batch_size; ++batch)
{
- case DataType::FLOAT32:
- evalFloat();
- break;
- default:
- assert(false && "Unsupported type.");
+ for (int outer = 0; outer < outer_size; ++outer)
+ {
+ for (int coord = 0; coord < coord_size; ++coord)
+ {
+ auto x = coords_data[coord];
+ std::memcpy(
+ output_data + (((batch * outer_size) + outer) * coord_size + coord) * inner_size,
+ input_data +
+ (((batch * outer_size) + outer) * axis_size + coords_data[batch * coord_size + coord]) *
+ inner_size,
+ sizeof(InputT) * inner_size);
+ }
+ }
}
}
-void Gather::evalFloat() const
+} // namespace
+
+void configure_kernel_CircleGather(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- assert(indices()->element_type() == DataType::S32 || indices()->element_type() == DataType::S64);
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
- const auto params_data = getTensorData<float>(params());
- auto output_data = getTensorData<float>(output());
+ const auto *options = cur_op->builtin_options_as_GatherOptions();
- tflite::GatherParams tparams;
- tparams.axis = _params.axis;
- tparams.batch_dims = _params.batch_dims;
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input2()) == DataType::S32);
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) == DataType::FLOAT32 or
+ Tensor::element_type(kernel.input1()) == DataType::S8 or
+ Tensor::element_type(kernel.input1()) == DataType::S32);
- if (indices()->element_type() == DataType::S32)
+ int32_t axis = options->axis();
+ int32_t num_dims = Tensor::num_dims(kernel.input1());
+ if (axis < 0)
{
- const auto indices_data = getTensorData<int32_t>(indices());
+ axis += num_dims;
+ }
+
+ LUCI_INTERPRETER_CHECK(axis >= 0 and axis < num_dims);
- luci_interpreter_pal::Gather<float, int32_t>(tparams, getTensorShape(params()), params_data,
- getTensorShape(indices()), indices_data,
- getTensorShape(output()), output_data);
+ int32_t batch_dims = options->batch_dims();
+ int32_t coords_num_dims = Tensor::num_dims(kernel.input2());
+ // batch_dims should be in range: [-rank(coords), rank(coords)].
+ // Negative batch_dims is added with rank of coords.
+ if (batch_dims < 0)
+ {
+ batch_dims += coords_num_dims;
}
- else
+ LUCI_INTERPRETER_CHECK(batch_dims <= axis);
+ LUCI_INTERPRETER_CHECK(batch_dims >= 0 and batch_dims < num_dims);
+ LUCI_INTERPRETER_CHECK(batch_dims <= coords_num_dims);
+ for (int i = 0; i < batch_dims; ++i)
{
- const auto indices_data = getTensorData<int64_t>(indices());
+ LUCI_INTERPRETER_CHECK(Tensor::dim(kernel.input1(), i) == Tensor::dim(kernel.input2(), i));
+ }
+}
+
+void execute_kernel_CircleGather(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
- luci_interpreter_pal::Gather<float, int64_t>(tparams, getTensorShape(params()), params_data,
- getTensorShape(indices()), indices_data,
- getTensorShape(output()), output_data);
+ const auto *options = cur_op->builtin_options_as_GatherOptions();
+
+ switch (Tensor::element_type(kernel.input1()))
+ {
+#ifndef DIS_FLOAT
+ case DataType::FLOAT32:
+ return gather<float, int32_t>(options, &kernel);
+#endif // DIS_FLOAT
+#ifndef DIS_QUANT
+ case DataType::S8:
+ return gather<int8_t, int32_t>(options, &kernel);
+#endif // DIS_QUANT
+ case DataType::S32:
+ return gather<int32_t, int32_t>(options, &kernel);
+ default:
+ assert(false && "Unsupported type");
}
}
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Gather.h b/onert-micro/luci-interpreter/src/kernels/Gather.h
deleted file mode 100644
index 5a36c82d6..000000000
--- a/onert-micro/luci-interpreter/src/kernels/Gather.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_GATHER_H
-#define LUCI_INTERPRETER_KERNELS_GATHER_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Gather : public KernelWithParams<GatherParams>
-{
-public:
- Gather(const Tensor *params, const Tensor *indices, Tensor *output, const GatherParams &gparams);
-
- const Tensor *params() const { return _inputs[0]; }
- const Tensor *indices() const { return _inputs[1]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-
-private:
- void evalFloat() const;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_GATHER_H
diff --git a/onert-micro/luci-interpreter/src/kernels/Gather.test.cpp b/onert-micro/luci-interpreter/src/kernels/Gather.test.cpp
index dacf366c3..c1fa5efab 100644
--- a/onert-micro/luci-interpreter/src/kernels/Gather.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Gather.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,14 +14,15 @@
* limitations under the License.
*/
-#include "kernels/Gather.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/gather/FloatGatherKernel.h"
+#include "luci_interpreter/test_models/gather/IntGatherKernel.h"
+#include "luci_interpreter/test_models/gather/NegGatherKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
@@ -30,109 +30,93 @@ using namespace testing;
class GatherTest : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-TEST_F(GatherTest, Simple)
+template <typename T> std::vector<T> checkGatherKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- std::vector<float> params_data{1.f, 2.f, 3.f, 4.f, 5.f, 6.f};
- std::vector<int32_t> indices_data{1, 0, 1, 5};
- std::vector<float> ref_output_data{2.f, 1.f, 2.f, 6.f};
-
- Tensor params_tensor =
- makeInputTensor<DataType::FLOAT32>({1, 6}, params_data, _memory_manager.get());
- Tensor indices_tensor = makeInputTensor<DataType::S32>({4}, indices_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
- GatherParams gparams;
-
- gparams.axis = 1;
- gparams.batch_dims = 0;
-
- Gather kernel(&params_tensor, &indices_tensor, &output_tensor, gparams);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<float>(output_tensor),
- ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 4}));
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
+
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
+
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
+
+ runtime_module.execute();
+
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
+
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST_F(GatherTest, Simple_Batch)
+TEST_F(GatherTest, Gather_Float_P)
{
- Shape params_shape = {3, 5};
- Shape indices_shape = {3, 2};
- std::vector<float> params_data{0., 0., 1., 0., 2., 3., 0., 0., 0., 4., 0., 5., 0., 6., 0.};
- std::vector<int32_t> indices_data{2, 4, 0, 4, 1, 3};
- std::vector<float> ref_output_data{1., 2., 3., 4., 5., 6.};
-
- Tensor params_tensor =
- makeInputTensor<DataType::FLOAT32>(params_shape, params_data, _memory_manager.get());
- Tensor indices_tensor =
- makeInputTensor<DataType::S32>(indices_shape, indices_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
- GatherParams gparams;
-
- gparams.axis = 1;
- gparams.batch_dims = 1;
-
- Gather kernel(&params_tensor, &indices_tensor, &output_tensor, gparams);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<float>(output_tensor),
- ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({3, 2}));
+ test_kernel::TestDataFloatGather test_data_float_gather;
+ std::vector<float> output_data_vector = checkGatherKernel(&test_data_float_gather);
+ EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+ test_data_float_gather.get_output_data_by_index(0), 0.0001f));
}
-TEST_F(GatherTest, Simple_NEG)
+TEST_F(GatherTest, Gather_Int_P)
{
- Tensor params_tensor = makeInputTensor<DataType::S32>({1}, {1}, _memory_manager.get());
- Tensor indices_tensor = makeInputTensor<DataType::S32>({1}, {0}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
- GatherParams gparams;
-
- Gather kernel(&params_tensor, &indices_tensor, &output_tensor, gparams);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::TestDataIntGather test_data_int_gather;
+ std::vector<int32_t> output_data_vector = checkGatherKernel(&test_data_int_gather);
+ EXPECT_THAT(output_data_vector, test_data_int_gather.get_output_data_by_index(0));
}
-TEST_F(GatherTest, Axis_NEG)
+TEST_F(GatherTest, Input_output_type_mismatch_NEG)
{
- Tensor params_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor indices_tensor = makeInputTensor<DataType::S32>({1}, {0}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
- GatherParams gparams;
-
- gparams.axis = 100;
- gparams.batch_dims = 0;
-
- Gather kernel(&params_tensor, &indices_tensor, &output_tensor, gparams);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::NegTestDataInputOutputTypeMismatchGatherKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST_F(GatherTest, Batch_NEG)
+TEST_F(GatherTest, Wrong_position_type_NEG)
{
- std::vector<float> params_data{1.f, 2.f, 3.f, 4.f, 5.f, 6.f};
- std::vector<int32_t> indices_data{1, 0, 1, 5};
- std::vector<float> ref_output_data{2.f, 1.f, 2.f, 6.f};
-
- Tensor params_tensor =
- makeInputTensor<DataType::FLOAT32>({1, 6}, params_data, _memory_manager.get());
- Tensor indices_tensor = makeInputTensor<DataType::S32>({4}, indices_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
- GatherParams gparams;
-
- gparams.axis = 0;
- gparams.batch_dims = 1;
+ test_kernel::NegTestDataWrongPositionTypeGatherKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
+}
- Gather kernel(&params_tensor, &indices_tensor, &output_tensor, gparams);
- EXPECT_ANY_THROW(kernel.configure());
+TEST_F(GatherTest, Wrong_axis_NEG)
+{
+ test_kernel::NegTestDataWrongAxisGatherKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
+// TODO: add S8 test
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Greater.cpp b/onert-micro/luci-interpreter/src/kernels/Greater.cpp
index 68a0d4762..b073a4a67 100644
--- a/onert-micro/luci-interpreter/src/kernels/Greater.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Greater.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,128 +14,75 @@
* limitations under the License.
*/
-#include "kernels/Greater.h"
+#include "Builders.h"
#include "kernels/Utils.h"
+#include "TISOKernel.h"
-#include <tensorflow/lite/kernels/internal/reference/comparisons.h>
+#include "PALComparisons.h"
namespace luci_interpreter
{
-namespace kernels
+namespace
{
+// TODO: reduce code duplication with less
+template <typename T>
+void evalGeneric(const circle::Tensor *x, const circle::Tensor *y, const circle::Tensor *output,
+ BaseRuntimeGraph *runtime_graph)
+{
+ auto x_data = kernels::getTensorData<T>(runtime_graph->getDataByTensor(x));
+ if (x_data == nullptr)
+ x_data = kernels::getTensorData<T>(runtime_graph->getConstDataByTensor(x));
+
+ assert(x_data != nullptr);
+
+ auto y_data = kernels::getTensorData<T>(runtime_graph->getDataByTensor(y));
+ if (y_data == nullptr)
+ y_data = kernels::getTensorData<T>(runtime_graph->getConstDataByTensor(y));
+
+ assert(y_data != nullptr);
+
+ auto output_data = kernels::getTensorData<bool>(runtime_graph->getDataByTensor(output));
-Greater::Greater(const Tensor *x, const Tensor *y, Tensor *output) : Kernel({x, y}, {output}) {}
+ luci_interpreter_pal::ComparisonParams op_params;
+ op_params.is_broadcast = Tensor::num_elements(x) != Tensor::num_elements(y);
-void Greater::configure()
+ const int64_t flat_size = kernels::getTensorShape(x).flatSize();
+ luci_interpreter_pal::ComparisonNoScaling<T>(flat_size, x_data, y_data, output_data,
+ luci_interpreter_pal::GreaterFn);
+}
+
+} // namespace
+
+void configure_kernel_CircleGreater(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- LUCI_INTERPRETER_CHECK(x()->element_type() == y()->element_type());
- LUCI_INTERPRETER_CHECK(output()->element_type() == DataType::BOOL);
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
- if (x()->element_type() == DataType::U8)
- {
- quantizeMultiplierSmallerThanOneExp(x()->scale(), &_x_multiplier, &_x_shift);
- quantizeMultiplierSmallerThanOneExp(y()->scale(), &_y_multiplier, &_y_shift);
- }
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(calculateShapeForBroadcast(x()->shape(), y()->shape()));
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+ Tensor::element_type(kernel.input2()));
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.output()) == DataType::BOOL);
}
-void Greater::execute() const
+void execute_kernel_CircleGreater(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- switch (x()->element_type())
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
+
+ switch (Tensor::element_type(kernel.input1()))
{
- case DataType::FLOAT32:
- evalFloat();
- break;
case DataType::S64:
- evalInteger<int64_t>();
+ evalGeneric<int64_t>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
break;
case DataType::S32:
- evalInteger<int32_t>();
+ evalGeneric<int32_t>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
break;
- case DataType::U8:
- evalQuantized();
+#ifndef DIS_FLOAT
+ case DataType::FLOAT32:
+ evalGeneric<float>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
break;
+#endif // DIS_FLOAT
default:
assert(false && "Unsupported type.");
}
}
-void Greater::evalFloat() const
-{
- const auto x_data = getTensorData<float>(x());
- const auto y_data = getTensorData<float>(y());
- auto output_data = getTensorData<bool>(output());
-
- tflite::ComparisonParams op_params;
- op_params.is_broadcast = x()->shape() != y()->shape();
-
- if (op_params.is_broadcast)
- {
- tflite::reference_ops::Broadcast4DSlowGreater(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data,
- getTensorShape(output()), output_data);
- }
- else
- {
- tflite::reference_ops::Greater(op_params, getTensorShape(x()), x_data, getTensorShape(y()),
- y_data, getTensorShape(output()), output_data);
- }
-}
-
-template <typename T> void Greater::evalInteger() const
-{
- const auto x_data = getTensorData<T>(x());
- const auto y_data = getTensorData<T>(y());
- auto output_data = getTensorData<bool>(output());
-
- tflite::ComparisonParams op_params;
- op_params.is_broadcast = x()->shape() != y()->shape();
-
- if (op_params.is_broadcast)
- {
- tflite::reference_ops::Broadcast4DSlowGreaterNoScaling(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data,
- getTensorShape(output()), output_data);
- }
- else
- {
- tflite::reference_ops::GreaterNoScaling(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data, getTensorShape(output()),
- output_data);
- }
-}
-
-void Greater::evalQuantized() const
-{
- const auto x_data = getTensorData<uint8_t>(x());
- const auto y_data = getTensorData<uint8_t>(y());
- auto output_data = getTensorData<bool>(output());
-
- tflite::ComparisonParams op_params;
- op_params.left_shift = 8;
- op_params.input1_offset = -x()->zero_point(); // Note the '-'
- op_params.input1_shift = _x_shift;
- op_params.input1_multiplier = _x_multiplier;
- op_params.input2_offset = -y()->zero_point(); // Note the '-'
- op_params.input2_shift = _y_shift;
- op_params.input2_multiplier = _y_multiplier;
- op_params.is_broadcast = x()->shape() != y()->shape();
-
- if (op_params.is_broadcast)
- {
- tflite::reference_ops::Broadcast4DSlowGreaterWithScaling(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data,
- getTensorShape(output()), output_data);
- }
- else
- {
- tflite::reference_ops::GreaterWithScaling(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data, getTensorShape(output()),
- output_data);
- }
-}
-
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Greater.test.cpp b/onert-micro/luci-interpreter/src/kernels/Greater.test.cpp
index a48080124..cd938f00d 100644
--- a/onert-micro/luci-interpreter/src/kernels/Greater.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Greater.test.cpp
@@ -15,14 +15,13 @@
* limitations under the License.
*/
-#include "kernels/Greater.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/greater/FloatGreaterKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
@@ -30,305 +29,61 @@ using namespace testing;
class GreaterTest : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-TEST_F(GreaterTest, FloatSimple)
-{
- std::vector<float> x_data{
- 0.5, 0.7, 0.9, // Row 1
- 1, 0, -1, // Row 2
- };
-
- std::vector<float> y_data{
- 0.9, 0.7, 0.5, // Row 1
- -1, 0, 1, // Row 2
- };
-
- std::vector<bool> ref_output_data{
- false, false, true, // Row 1
- true, false, false, // Row 2
- };
-
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Greater kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({2, 3}));
-}
-
-TEST_F(GreaterTest, FloatBroardcast)
-{
- std::vector<float> x_data{
- 0.5, 0.7, 0.9, // Row 1
- 1, 0, -1, // Row 2
- -1, 0, 1, // Row 3
- };
-
- std::vector<float> y_data{
- 0.9, 0.7, 0.5, // Row 1
- };
-
- std::vector<bool> ref_output_data{
- false, false, true, // Row 1
- true, false, false, // Row 2
- false, false, true, // Row 3
- };
-
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({3, 3}, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({1, 3}, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Greater kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({3, 3}));
-}
-
-template <loco::DataType DType>
-void checkIntegerSimple(luci_interpreter::IMemoryManager *memory_manager)
+template <typename T, typename U>
+std::vector<U> checkGreaterKernel(test_kernel::TestDataBase<T, U> *test_data_base)
{
- using dtype = typename loco::DataTypeImpl<DType>::Type;
- dtype min_value = std::numeric_limits<dtype>::min();
- dtype max_value = std::numeric_limits<dtype>::max();
- std::vector<dtype> x_data{min_value, 2, max_value};
-
- std::vector<dtype> y_data{min_value + 1, -2, max_value};
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- std::vector<bool> ref_output_data{false, true, false};
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- Tensor x_tensor = makeInputTensor<DType>({3}, x_data, memory_manager);
- Tensor y_tensor = makeInputTensor<DType>({3}, y_data, memory_manager);
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 2);
- Greater kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ // set left input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({3}));
-}
-
-template <loco::DataType DType>
-void checkIntegerBroadcast(luci_interpreter::IMemoryManager *memory_manager)
-{
- using dtype = typename loco::DataTypeImpl<DType>::Type;
- dtype min_value = std::numeric_limits<dtype>::min();
- dtype max_value = std::numeric_limits<dtype>::max();
- std::vector<dtype> x_data{
- min_value, 2, 3, // Row 1
- 4, 5, max_value, // Row 2
- -1, -4, -3, // Row 3
- min_value, -2, max_value, // Row 4
- };
+ // set right input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(1));
+ std::copy(test_data_base->get_input_data_by_index(1).begin(),
+ test_data_base->get_input_data_by_index(1).end(), input_tensor_data);
+ }
- std::vector<dtype> y_data{
- min_value + 1, -2, max_value - 1, // Row 1
- };
+ runtime_module.execute();
- std::vector<bool> ref_output_data{
- false, true, false, // Row 1
- true, true, true, // Row 2
- true, false, false, // Row 3
- false, false, true, // Row 4
- };
-
- Tensor x_tensor = makeInputTensor<DType>({4, 3}, x_data, memory_manager);
- Tensor y_tensor = makeInputTensor<DType>({3}, y_data, memory_manager);
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Greater kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({4, 3}));
-}
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
-TEST_F(GreaterTest, Int32)
-{
- checkIntegerSimple<loco::DataType::S32>(_memory_manager.get());
- checkIntegerBroadcast<loco::DataType::S32>(_memory_manager.get());
- SUCCEED();
+ U *output_data = reinterpret_cast<U *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(U));
+ std::vector<U> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST_F(GreaterTest, Int64)
+TEST_F(GreaterTest, FloatNoBroadcast_P)
{
- checkIntegerSimple<loco::DataType::S64>(_memory_manager.get());
- checkIntegerBroadcast<loco::DataType::S64>(_memory_manager.get());
- SUCCEED();
+ const bool is_with_broadcast = false;
+ test_kernel::TestDataFloatGreater test_data_kernel(is_with_broadcast, false);
+ std::vector<bool> output_data_vector = checkGreaterKernel<float, bool>(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-// Choose min / max in such a way that there are exactly 256 units to avoid rounding errors.
-const float F_MIN = -128.0 / 128.0;
-const float F_MAX = 127.0 / 128.0;
-
-TEST_F(GreaterTest, Uint8Quantized)
+TEST_F(GreaterTest, FloatNoBroadcast_NEG)
{
- std::vector<float> x_data{
- 0.5, 0.6, 0.7, 0.9, // Row 1
- 1, 0, 0.05, -1, // Row 2
- };
-
- std::vector<float> y_data{
- 0.9, 0.6, 0.6, 0.5, // Row 1
- -1, 0.05, 0, 1, // Row 2
- };
-
- std::vector<bool> ref_output_data{
- false, false, true, true, // Row 1
- true, false, true, false, // Row 2
- };
-
- std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
- Tensor x_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, quant_param.first, quant_param.second, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, quant_param.first, quant_param.second, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Greater kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 4, 1}));
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
-}
-
-TEST_F(GreaterTest, Uint8QuantizedRescale)
-{
- std::vector<float> x_data{
- 0.5, 0.6, 0.7, 0.9, // Row 1
- 1, 0, 0.05, -1, // Row 2
- };
-
- std::vector<float> y_data{
- 0.9, 0.6, 0.6, 0.5, // Row 1
- -1, 0.05, 0, 1, // Row 2
- };
-
- std::vector<bool> ref_output_data{
- false, false, true, true, // Row 1
- true, false, true, false, // Row 2
- };
-
- std::pair<float, int32_t> x_quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
- std::pair<float, int32_t> y_quant_param = quantizationParams<uint8_t>(F_MIN * 2, F_MAX * 3);
-
- Tensor x_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, x_quant_param.first, x_quant_param.second, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, y_quant_param.first, y_quant_param.second, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Greater kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 4, 1}));
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
-}
-
-TEST_F(GreaterTest, Uint8QuantizedBroadcast)
-{
- std::vector<float> x_data{
- 0.4, -0.8, 0.7, 0.3, // Row 1
- -0.5, 0.1, 0, 0.5, // Row 2
- 1, 0, 0.05, -1, // Row 3
- };
-
- std::vector<float> y_data{
- -1, 0.05, 0, 1, // Row 1
- };
-
- std::vector<bool> ref_output_data{
- true, false, true, false, // Row 1
- true, true, false, false, // Row 2
- true, false, true, false, // Row 3
- };
-
- std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
- Tensor x_tensor = makeInputTensor<DataType::U8>(
- {1, 3, 4, 1}, quant_param.first, quant_param.second, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::U8>(
- {1, 1, 4, 1}, quant_param.first, quant_param.second, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Greater kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 3, 4, 1}));
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
-}
-
-TEST_F(GreaterTest, Input_Type_Mismatch_NEG)
-{
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::U8>({1}, {1}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Greater kernel(&x_tensor, &y_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(GreaterTest, Input_Output_Type_NEG)
-{
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- Greater kernel(&x_tensor, &y_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(GreaterTest, Float_Broadcast_NEG)
-{
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({2}, {1.f, 2.f}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({3}, {1.f, 2.f, 3.f}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Greater kernel(&x_tensor, &y_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(GreaterTest, Int32_Broadcast_NEG)
-{
- Tensor x_tensor = makeInputTensor<DataType::S32>({2}, {1, 2}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::S32>({3}, {1, 2, 3}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Greater kernel(&x_tensor, &y_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(GreaterTest, Int64_Broadcast_NEG)
-{
- Tensor x_tensor = makeInputTensor<DataType::S64>({2}, {1, 2}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::S64>({3}, {1, 2, 3}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Greater kernel(&x_tensor, &y_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
+ const bool is_with_broadcast = false;
+ test_kernel::TestDataFloatGreater test_data_kernel(is_with_broadcast, true);
+ EXPECT_DEATH(checkGreaterKernel(&test_data_kernel), "");
}
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/GreaterEqual.cpp b/onert-micro/luci-interpreter/src/kernels/GreaterEqual.cpp
index c2a7dcee3..dfb585d5a 100644
--- a/onert-micro/luci-interpreter/src/kernels/GreaterEqual.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/GreaterEqual.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,131 +14,77 @@
* limitations under the License.
*/
-#include "kernels/GreaterEqual.h"
+#include "Builders.h"
#include "kernels/Utils.h"
+#include "TISOKernel.h"
-#include <tensorflow/lite/kernels/internal/reference/comparisons.h>
+#include "PALComparisons.h"
namespace luci_interpreter
{
-namespace kernels
+namespace
{
-
-GreaterEqual::GreaterEqual(const Tensor *x, const Tensor *y, Tensor *output)
- : Kernel({x, y}, {output})
+// TODO: reduce code duplication with less
+template <typename T>
+void evalGeneric(const circle::Tensor *x, const circle::Tensor *y, const circle::Tensor *output,
+ BaseRuntimeGraph *runtime_graph)
{
+ auto x_data = kernels::getTensorData<T>(runtime_graph->getDataByTensor(x));
+ if (x_data == nullptr)
+ x_data = kernels::getTensorData<T>(runtime_graph->getConstDataByTensor(x));
+
+ assert(x_data != nullptr);
+
+ auto y_data = kernels::getTensorData<T>(runtime_graph->getDataByTensor(y));
+ if (y_data == nullptr)
+ y_data = kernels::getTensorData<T>(runtime_graph->getConstDataByTensor(y));
+
+ assert(y_data != nullptr);
+
+ auto output_data = kernels::getTensorData<bool>(runtime_graph->getDataByTensor(output));
+
+ luci_interpreter_pal::ComparisonParams op_params;
+ op_params.is_broadcast = Tensor::num_elements(x) != Tensor::num_elements(y);
+
+ const int64_t flat_size = kernels::getTensorShape(x).flatSize();
+ luci_interpreter_pal::ComparisonNoScaling<T>(flat_size, x_data, y_data, output_data,
+ luci_interpreter_pal::GreaterEqualFn);
}
-void GreaterEqual::configure()
+} // namespace
+
+void configure_kernel_CircleGreaterEqual(const circle::Operator *cur_op,
+ BaseRuntimeGraph *runtime_graph)
{
- LUCI_INTERPRETER_CHECK(x()->element_type() == y()->element_type());
- LUCI_INTERPRETER_CHECK(output()->element_type() == DataType::BOOL);
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
- if (x()->element_type() == DataType::U8)
- {
- quantizeMultiplierSmallerThanOneExp(x()->scale(), &_x_multiplier, &_x_shift);
- quantizeMultiplierSmallerThanOneExp(y()->scale(), &_y_multiplier, &_y_shift);
- }
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(calculateShapeForBroadcast(x()->shape(), y()->shape()));
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+ Tensor::element_type(kernel.input2()));
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.output()) == DataType::BOOL);
}
-void GreaterEqual::execute() const
+void execute_kernel_CircleGreaterEqual(const circle::Operator *cur_op,
+ BaseRuntimeGraph *runtime_graph)
{
- switch (x()->element_type())
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
+
+ switch (Tensor::element_type(kernel.input1()))
{
- case DataType::FLOAT32:
- evalFloat();
- break;
case DataType::S64:
- evalInteger<int64_t>();
+ evalGeneric<int64_t>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
break;
case DataType::S32:
- evalInteger<int32_t>();
+ evalGeneric<int32_t>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
break;
- case DataType::U8:
- evalQuantized();
+#ifndef DIS_FLOAT
+ case DataType::FLOAT32:
+ evalGeneric<float>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
break;
+#endif // DIS_FLOAT
default:
assert(false && "Unsupported type.");
}
}
-void GreaterEqual::evalFloat() const
-{
- const auto x_data = getTensorData<float>(x());
- const auto y_data = getTensorData<float>(y());
- auto output_data = getTensorData<bool>(output());
-
- tflite::ComparisonParams op_params;
- op_params.is_broadcast = x()->shape() != y()->shape();
-
- if (op_params.is_broadcast)
- {
- tflite::reference_ops::Broadcast4DSlowGreaterEqual(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data,
- getTensorShape(output()), output_data);
- }
- else
- {
- tflite::reference_ops::GreaterEqual(op_params, getTensorShape(x()), x_data, getTensorShape(y()),
- y_data, getTensorShape(output()), output_data);
- }
-}
-
-template <typename T> void GreaterEqual::evalInteger() const
-{
- const auto x_data = getTensorData<T>(x());
- const auto y_data = getTensorData<T>(y());
- auto output_data = getTensorData<bool>(output());
-
- tflite::ComparisonParams op_params;
- op_params.is_broadcast = x()->shape() != y()->shape();
-
- if (op_params.is_broadcast)
- {
- tflite::reference_ops::Broadcast4DSlowGreaterEqualNoScaling(
- op_params, getTensorShape(x()), x_data, getTensorShape(y()), y_data, getTensorShape(output()),
- output_data);
- }
- else
- {
- tflite::reference_ops::GreaterEqualNoScaling(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data,
- getTensorShape(output()), output_data);
- }
-}
-
-void GreaterEqual::evalQuantized() const
-{
- const auto x_data = getTensorData<uint8_t>(x());
- const auto y_data = getTensorData<uint8_t>(y());
- auto output_data = getTensorData<bool>(output());
-
- tflite::ComparisonParams op_params;
- op_params.left_shift = 8;
- op_params.input1_offset = -x()->zero_point(); // Note the '-'
- op_params.input1_shift = _x_shift;
- op_params.input1_multiplier = _x_multiplier;
- op_params.input2_offset = -y()->zero_point(); // Note the '-'
- op_params.input2_shift = _y_shift;
- op_params.input2_multiplier = _y_multiplier;
- op_params.is_broadcast = x()->shape() != y()->shape();
-
- if (op_params.is_broadcast)
- {
- tflite::reference_ops::Broadcast4DSlowGreaterEqualWithScaling(
- op_params, getTensorShape(x()), x_data, getTensorShape(y()), y_data, getTensorShape(output()),
- output_data);
- }
- else
- {
- tflite::reference_ops::GreaterEqualWithScaling(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data,
- getTensorShape(output()), output_data);
- }
-}
-
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/GreaterEqual.h b/onert-micro/luci-interpreter/src/kernels/GreaterEqual.h
deleted file mode 100644
index 64f4f4cc4..000000000
--- a/onert-micro/luci-interpreter/src/kernels/GreaterEqual.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_GREATER_EQUAL_H
-#define LUCI_INTERPRETER_KERNELS_GREATER_EQUAL_H
-
-#include "core/Kernel.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class GreaterEqual : public Kernel
-{
-public:
- GreaterEqual(const Tensor *x, const Tensor *y, Tensor *output);
-
- const Tensor *x() const { return _inputs[0]; }
- const Tensor *y() const { return _inputs[1]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-
-private:
- void evalFloat() const;
- template <typename T> void evalInteger() const;
- void evalQuantized() const;
-
-private:
- int32_t _x_multiplier = 0;
- int _x_shift = 0;
- int32_t _y_multiplier = 0;
- int _y_shift = 0;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_GREATER_EQUAL_H
diff --git a/onert-micro/luci-interpreter/src/kernels/GreaterEqual.test.cpp b/onert-micro/luci-interpreter/src/kernels/GreaterEqual.test.cpp
index 35bf88eab..4bc2e2b36 100644
--- a/onert-micro/luci-interpreter/src/kernels/GreaterEqual.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/GreaterEqual.test.cpp
@@ -15,14 +15,13 @@
* limitations under the License.
*/
-#include "kernels/GreaterEqual.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/greater_equal/FloatGreaterEqualKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
@@ -30,304 +29,61 @@ using namespace testing;
class GreaterEqualTest : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-TEST_F(GreaterEqualTest, FloatSimple)
-{
- std::vector<float> x_data{
- 0.5, 0.7, 0.9, // Row 1
- 1, 0, -1, // Row 2
- };
-
- std::vector<float> y_data{
- 0.9, 0.7, 0.5, // Row 1
- -1, 0, 1, // Row 2
- };
-
- std::vector<bool> ref_output_data{
- false, true, true, // Row 1
- true, true, false, // Row 2
- };
-
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- GreaterEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({2, 3}));
-}
-
-TEST_F(GreaterEqualTest, FloatBroardcast)
-{
- std::vector<float> x_data{
- 0.5, 0.7, 0.9, // Row 1
- 1, 0, -1, // Row 2
- -1, 0, 1, // Row 3
- };
-
- std::vector<float> y_data{
- 0.9, 0.7, 0.5, // Row 1
- };
-
- std::vector<bool> ref_output_data{
- false, true, true, // Row 1
- true, false, false, // Row 2
- false, false, true, // Row 3
- };
-
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({3, 3}, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({1, 3}, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- GreaterEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({3, 3}));
-}
-template <loco::DataType DType>
-void checkIntegerSimple(luci_interpreter::IMemoryManager *memory_manager)
-{
- using dtype = typename loco::DataTypeImpl<DType>::Type;
- dtype min_value = std::numeric_limits<dtype>::min();
- dtype max_value = std::numeric_limits<dtype>::max();
- std::vector<dtype> x_data{min_value, 2, max_value};
-
- std::vector<dtype> y_data{min_value + 1, -2, max_value};
-
- std::vector<bool> ref_output_data{false, true, true};
-
- Tensor x_tensor = makeInputTensor<DType>({3}, x_data, memory_manager);
- Tensor y_tensor = makeInputTensor<DType>({3}, y_data, memory_manager);
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- GreaterEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({3}));
-}
-
-template <loco::DataType DType>
-void checkIntegerBroadcast(luci_interpreter::IMemoryManager *memory_manager)
-{
- using dtype = typename loco::DataTypeImpl<DType>::Type;
- dtype min_value = std::numeric_limits<dtype>::min();
- dtype max_value = std::numeric_limits<dtype>::max();
- std::vector<dtype> x_data{
- min_value, 2, 3, // Row 1
- 4, 5, max_value, // Row 2
- -1, -4, -3, // Row 3
- min_value, -2, max_value - 1, // Row 4
- };
-
- std::vector<dtype> y_data{
- min_value + 1, -2, max_value - 1, // Row 1
- };
-
- std::vector<bool> ref_output_data{
- false, true, false, // Row 1
- true, true, true, // Row 2
- true, false, false, // Row 3
- false, true, true, // Row 4
- };
-
- Tensor x_tensor = makeInputTensor<DType>({4, 3}, x_data, memory_manager);
- Tensor y_tensor = makeInputTensor<DType>({3}, y_data, memory_manager);
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- GreaterEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({4, 3}));
-}
-
-TEST_F(GreaterEqualTest, Int32)
-{
- checkIntegerSimple<loco::DataType::S32>(_memory_manager.get());
- checkIntegerBroadcast<loco::DataType::S32>(_memory_manager.get());
- SUCCEED();
-}
-
-TEST_F(GreaterEqualTest, Int64)
+template <typename T, typename U>
+std::vector<U> checkGreaterEqualKernel(test_kernel::TestDataBase<T, U> *test_data_base)
{
- checkIntegerSimple<loco::DataType::S64>(_memory_manager.get());
- checkIntegerBroadcast<loco::DataType::S64>(_memory_manager.get());
- SUCCEED();
-}
-
-// Choose min / max in such a way that there are exactly 256 units to avoid rounding errors.
-const float F_MIN = -128.0 / 128.0;
-const float F_MAX = 127.0 / 128.0;
-
-TEST_F(GreaterEqualTest, Uint8Quantized)
-{
- std::vector<float> x_data{
- 0.5, 0.6, 0.7, 0.9, // Row 1
- 1, 0, 0.05, -1, // Row 2
- };
-
- std::vector<float> y_data{
- 0.9, 0.6, 0.55, 0.5, // Row 1
- -1, 0.05, 0, 1, // Row 2
- };
-
- std::vector<bool> ref_output_data{
- false, true, true, true, // Row 1
- true, false, true, false, // Row 2
- };
-
- std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
- Tensor x_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, quant_param.first, quant_param.second, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, quant_param.first, quant_param.second, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- GreaterEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 4, 1}));
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
-}
-
-TEST_F(GreaterEqualTest, Uint8QuantizedRescale)
-{
- std::vector<float> x_data{
- 0.5, 0.5, 0.7, 0.9, // Row 1
- 1, 0, 0.05, -1, // Row 2
- };
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 2);
- std::vector<float> y_data{
- 0.9, 0.5, 0.6, 0.5, // Row 1
- -1, 0.05, 0, 1, // Row 2
- };
+ // set left input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
- std::vector<bool> ref_output_data{
- false, true, true, true, // Row 1
- true, false, true, false, // Row 2
- };
+ // set right input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(1));
+ std::copy(test_data_base->get_input_data_by_index(1).begin(),
+ test_data_base->get_input_data_by_index(1).end(), input_tensor_data);
+ }
- std::pair<float, int32_t> x_quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
- std::pair<float, int32_t> y_quant_param = quantizationParams<uint8_t>(F_MIN * 1.2, F_MAX * 1.5);
+ runtime_module.execute();
- Tensor x_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, x_quant_param.first, x_quant_param.second, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, y_quant_param.first, y_quant_param.second, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
- GreaterEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 4, 1}));
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
+ U *output_data = reinterpret_cast<U *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(U));
+ std::vector<U> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST_F(GreaterEqualTest, Uint8QuantizedBroadcast)
+TEST_F(GreaterEqualTest, FloatNoBroadcast_P)
{
- std::vector<float> x_data{
- 0.4, -0.8, 0.7, 0.3, // Row 1
- -0.5, 0.1, 0, 0.5, // Row 2
- 1, 0, 0.05, -1, // Row 3
- };
-
- std::vector<float> y_data{
- -1, 0.05, 0, 1, // Row 1
- };
-
- std::vector<bool> ref_output_data{
- true, false, true, false, // Row 1
- true, true, true, false, // Row 2
- true, false, true, false, // Row 3
- };
-
- std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
- Tensor x_tensor = makeInputTensor<DataType::U8>(
- {1, 3, 4, 1}, quant_param.first, quant_param.second, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::U8>(
- {1, 1, 4, 1}, quant_param.first, quant_param.second, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- GreaterEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 3, 4, 1}));
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
+ const bool is_with_broadcast = false;
+ test_kernel::TestDataFloatGreaterEqual test_data_kernel(is_with_broadcast, false);
+ std::vector<bool> output_data_vector = checkGreaterEqualKernel<float, bool>(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-TEST_F(GreaterEqualTest, Input_Type_Mismatch_NEG)
+TEST_F(GreaterEqualTest, FloatNoBroadcast_NEG)
{
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::U8>({1}, {1}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- GreaterEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(GreaterEqualTest, Input_Output_Type_NEG)
-{
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- GreaterEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(GreaterEqualTest, Float_Broadcast_NEG)
-{
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({2}, {1.f, 2.f}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({3}, {1.f, 2.f, 3.f}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- GreaterEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(GreaterEqualTest, Int32_Broadcast_NEG)
-{
- Tensor x_tensor = makeInputTensor<DataType::S32>({2}, {1, 2}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::S32>({3}, {1, 2, 3}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- GreaterEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(GreaterEqualTest, Int64_Broadcast_NEG)
-{
- Tensor x_tensor = makeInputTensor<DataType::S64>({2}, {1, 2}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::S64>({3}, {1, 2, 3}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- GreaterEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
+ const bool is_with_broadcast = false;
+ test_kernel::TestDataFloatGreaterEqual test_data_kernel(is_with_broadcast, true);
+ EXPECT_DEATH(checkGreaterEqualKernel(&test_data_kernel), "");
}
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/If.cpp b/onert-micro/luci-interpreter/src/kernels/If.cpp
index b472323ac..971708bca 100644
--- a/onert-micro/luci-interpreter/src/kernels/If.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/If.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/If.h b/onert-micro/luci-interpreter/src/kernels/If.h
index 22bb2dc19..fa6ab371a 100644
--- a/onert-micro/luci-interpreter/src/kernels/If.h
+++ b/onert-micro/luci-interpreter/src/kernels/If.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/InstanceNorm.cpp b/onert-micro/luci-interpreter/src/kernels/InstanceNorm.cpp
index dc0fec9c7..577dc6454 100644
--- a/onert-micro/luci-interpreter/src/kernels/InstanceNorm.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/InstanceNorm.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/InstanceNorm.h b/onert-micro/luci-interpreter/src/kernels/InstanceNorm.h
index 77922e745..a70a84e0a 100644
--- a/onert-micro/luci-interpreter/src/kernels/InstanceNorm.h
+++ b/onert-micro/luci-interpreter/src/kernels/InstanceNorm.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/InstanceNorm.test.cpp b/onert-micro/luci-interpreter/src/kernels/InstanceNorm.test.cpp
index 976f1b597..04400c3c0 100644
--- a/onert-micro/luci-interpreter/src/kernels/InstanceNorm.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/InstanceNorm.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/KernelBuilder.cpp b/onert-micro/luci-interpreter/src/kernels/KernelBuilder.cpp
index 4b2e6627f..5d1e885d0 100644
--- a/onert-micro/luci-interpreter/src/kernels/KernelBuilder.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/KernelBuilder.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,29 +15,13 @@
*/
#include "KernelBuilder.h"
-#include "Builders.h"
namespace luci_interpreter
{
-KernelConfigureRegistry::KernelConfigureRegistry()
-{
-#define REGISTER_KERNEL(builtin_operator, name) \
- register_kernel_configure(circle::BuiltinOperator::BuiltinOperator_##builtin_operator, \
- configure_kernel_Circle##name);
-
-#if USE_GENERATED_LIST
-#include "GeneratedKernelsToBuild.lst"
-#else
-#include "KernelsToBuild.lst"
-#endif
-
-#undef REGISTER_KERNEL
-}
-
void KernelConfigureRegistry::configure_kernel(const circle::Operator *cur_op,
circle::BuiltinOperator opcode,
- BaseRuntimeGraph *runtime_graph)
+ BaseRuntimeGraph *runtime_graph) const
{
auto specific_configure_func = get_kernel_configure_func(opcode);
if (specific_configure_func == nullptr)
@@ -47,30 +30,15 @@ void KernelConfigureRegistry::configure_kernel(const circle::Operator *cur_op,
specific_configure_func(cur_op, runtime_graph);
}
-KernelExecuteRegistry::KernelExecuteRegistry()
-{
-#define REGISTER_KERNEL(builtin_operator, name) \
- register_kernel_execute(circle::BuiltinOperator::BuiltinOperator_##builtin_operator, \
- execute_kernel_Circle##name);
-
-#if USE_GENERATED_LIST
-#include "GeneratedKernelsToBuild.lst"
-#else
-#include "KernelsToBuild.lst"
-#endif
-
-#undef REGISTER_KERNEL
-}
-
void KernelExecuteRegistry::execute_kernel(const circle::Operator *cur_op,
circle::BuiltinOperator opcode,
- BaseRuntimeGraph *runtime_graph, bool is_inplace)
+ BaseRuntimeGraph *runtime_graph) const
{
auto specific_execute_func = get_kernel_execute_func(opcode);
if (specific_execute_func == nullptr)
assert(false && "Unsupported operator");
- specific_execute_func(cur_op, runtime_graph, is_inplace);
+ specific_execute_func(cur_op, runtime_graph);
}
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/KernelBuilder.h b/onert-micro/luci-interpreter/src/kernels/KernelBuilder.h
index 06da6530f..3d10f4918 100644
--- a/onert-micro/luci-interpreter/src/kernels/KernelBuilder.h
+++ b/onert-micro/luci-interpreter/src/kernels/KernelBuilder.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,73 +17,135 @@
#ifndef LUCI_INTERPRETER_KERNEL_KERNELBUILDER_H
#define LUCI_INTERPRETER_KERNEL_KERNELBUILDER_H
-#include "core/RuntimeGraph.h"
+#include "core/RuntimeModule.h"
#include "luci_interpreter/core/reader/CircleMicroReader.h"
+#include "Builders.h"
#include <memory>
#include <unordered_map>
namespace luci_interpreter
{
-namespace
+#define REGISTER_KERNEL(builtin_operator, name) BuiltinOperator_##builtin_operator,
+
+enum class BuilderID
+{
+#if USE_GENERATED_LIST
+#include "GeneratedKernelsToBuild.lst"
+#else
+#include "KernelsToBuild.lst"
+#endif
+ Size // casts to count of values in BuilderId enum
+};
+
+#undef REGISTER_KERNEL
+
+constexpr BuilderID get_builder_id(circle::BuiltinOperator opcode)
{
-#ifdef USE_STATIC_ALLOC
-using BaseRuntimeGraph = StaticRuntimeGraph;
+ switch (opcode)
+ {
+#define REGISTER_KERNEL(builtin_operator, name) \
+ case circle::BuiltinOperator_##builtin_operator: \
+ return BuilderID::BuiltinOperator_##builtin_operator;
+
+#if USE_GENERATED_LIST
+#include "GeneratedKernelsToBuild.lst"
#else
-using BaseRuntimeGraph = RuntimeGraph;
+#include "KernelsToBuild.lst"
#endif
-} // namespace
+
+#undef REGISTER_KERNEL
+ default:
+ assert(false && "Unsupported operation");
+ }
+}
class KernelConfigureRegistry
{
public:
using KernelConfigureFunc = void(const circle::Operator *, BaseRuntimeGraph *);
- KernelConfigureRegistry();
+ constexpr KernelConfigureRegistry() : _operator_configure()
+ {
+#define REGISTER_KERNEL(builtin_operator, name) \
+ register_kernel_configure(BuilderID::BuiltinOperator_##builtin_operator, \
+ configure_kernel_Circle##name);
- void configure_kernel(const circle::Operator *cur_op, circle::BuiltinOperator opcode,
- BaseRuntimeGraph *runtime_graph);
+#if USE_GENERATED_LIST
+#include "GeneratedKernelsToBuild.lst"
+#else
+#include "KernelsToBuild.lst"
+#endif
-private:
- std::unordered_map<int32_t, KernelConfigureFunc *> _operator_configure;
+#undef REGISTER_KERNEL
+ }
+
+ void configure_kernel(const circle::Operator *cur_op, circle::BuiltinOperator opcode,
+ BaseRuntimeGraph *runtime_graph) const;
private:
- KernelConfigureFunc *get_kernel_configure_func(circle::BuiltinOperator opcode) const
+ constexpr KernelConfigureFunc *get_kernel_configure_func(circle::BuiltinOperator opcode) const
{
- return _operator_configure.at(size_t(opcode));
+ const auto builder_id_opcode = size_t(get_builder_id(opcode));
+ assert(builder_id_opcode < size_t(BuilderID::Size));
+ return _operator_configure[builder_id_opcode];
}
- void register_kernel_configure(circle::BuiltinOperator id, KernelConfigureFunc *func)
+ constexpr void register_kernel_configure(BuilderID id, KernelConfigureFunc *func)
{
+ assert(size_t(id) < size_t(BuilderID::Size));
_operator_configure[size_t(id)] = func;
}
+
+private:
+ KernelConfigureFunc *_operator_configure[size_t(BuilderID::Size)];
};
class KernelExecuteRegistry
{
public:
- using KernelExecuteFunc = void(const circle::Operator *, BaseRuntimeGraph *, bool);
+ using KernelExecuteFunc = void(const circle::Operator *, BaseRuntimeGraph *);
- KernelExecuteRegistry();
+ constexpr KernelExecuteRegistry() : _operator_execute()
+ {
+#define REGISTER_KERNEL(builtin_operator, name) \
+ register_kernel_execute(BuilderID::BuiltinOperator_##builtin_operator, \
+ execute_kernel_Circle##name);
- void execute_kernel(const circle::Operator *cur_op, circle::BuiltinOperator opcode,
- BaseRuntimeGraph *runtime_graph, bool is_inplace);
+#if USE_GENERATED_LIST
+#include "GeneratedKernelsToBuild.lst"
+#else
+#include "KernelsToBuild.lst"
+#endif
-private:
- std::unordered_map<int32_t, KernelExecuteFunc *> _operator_execute;
+#undef REGISTER_KERNEL
+ }
+
+ void execute_kernel(const circle::Operator *cur_op, circle::BuiltinOperator opcode,
+ BaseRuntimeGraph *runtime_graph) const;
private:
- KernelExecuteFunc *get_kernel_execute_func(circle::BuiltinOperator opcode) const
+ constexpr KernelExecuteFunc *get_kernel_execute_func(circle::BuiltinOperator opcode) const
{
- return _operator_execute.at(size_t(opcode));
+ const auto tmp = size_t(get_builder_id(opcode));
+ assert(tmp < size_t(BuilderID::Size));
+ return _operator_execute[tmp];
}
- void register_kernel_execute(circle::BuiltinOperator id, KernelExecuteFunc *func)
+ constexpr void register_kernel_execute(BuilderID id, KernelExecuteFunc *func)
{
+ assert(size_t(id) < size_t(BuilderID::Size));
_operator_execute[size_t(id)] = func;
}
+
+private:
+ KernelExecuteFunc *_operator_execute[size_t(BuilderID::Size)];
};
+// Global constexpr kernel configure and kernel executor
+constexpr KernelConfigureRegistry kernel_configure;
+constexpr KernelExecuteRegistry kernel_executor;
+
} // namespace luci_interpreter
#endif // LUCI_INTERPRETER_KERNEL_KERNELBUILDER_H
diff --git a/onert-micro/luci-interpreter/src/kernels/L2Normalize.cpp b/onert-micro/luci-interpreter/src/kernels/L2Normalize.cpp
index 09482a5a1..97c9db86b 100644
--- a/onert-micro/luci-interpreter/src/kernels/L2Normalize.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/L2Normalize.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/L2Normalize.h b/onert-micro/luci-interpreter/src/kernels/L2Normalize.h
index 9c1716bd7..6c7dac698 100644
--- a/onert-micro/luci-interpreter/src/kernels/L2Normalize.h
+++ b/onert-micro/luci-interpreter/src/kernels/L2Normalize.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/L2Pool2D.h b/onert-micro/luci-interpreter/src/kernels/L2Pool2D.h
index 4d1ed5ddf..d40f5f478 100644
--- a/onert-micro/luci-interpreter/src/kernels/L2Pool2D.h
+++ b/onert-micro/luci-interpreter/src/kernels/L2Pool2D.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/LeakyRelu.cpp b/onert-micro/luci-interpreter/src/kernels/LeakyRelu.cpp
index ab7072fa8..7f032b5a0 100644
--- a/onert-micro/luci-interpreter/src/kernels/LeakyRelu.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/LeakyRelu.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,76 +14,66 @@
* limitations under the License.
*/
-#include "kernels/LeakyRelu.h"
-
+#include "Builders.h"
#include "kernels/Utils.h"
+#include "SISOKernel.h"
-#include <tensorflow/lite/kernels/internal/reference/leaky_relu.h>
-
-#include "PALLeakyRelu.h"
+#include "PALReluCommon.h"
namespace luci_interpreter
{
-namespace kernels
+void configure_kernel_CircleLeakyRelu(const circle::Operator *cur_op,
+ BaseRuntimeGraph *runtime_graph)
{
+ kernels::SISOKernel kernel(cur_op, runtime_graph);
-LeakyRelu::LeakyRelu(const Tensor *input, Tensor *output, const LeakyReluParams &params)
- : KernelWithParams<LeakyReluParams>({input}, {output}, params)
-{
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input()) ==
+ Tensor::element_type(kernel.output()));
+ LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.input()) == Tensor::num_dims(kernel.output()));
+ LUCI_INTERPRETER_CHECK(Tensor::num_elements(kernel.input()) ==
+ Tensor::num_elements(kernel.output()));
}
-void LeakyRelu::configure()
+void execute_kernel_CircleLeakyRelu(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
- if (input()->element_type() == DataType::U8)
- {
- double alpha_multiplier = input()->scale() * params().alpha / output()->scale();
- quantizeMultiplier(alpha_multiplier, &_output_multiplier_alpha, &_output_shift_alpha);
- double identity_multiplier = input()->scale() / output()->scale();
- quantizeMultiplier(identity_multiplier, &_output_multiplier_identity, &_output_shift_identity);
- }
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(input()->shape());
-}
+ kernels::SISOKernel kernel(cur_op, runtime_graph);
-void LeakyRelu::execute() const
-{
- switch (input()->element_type())
+ const auto *input_data = runtime_graph->getDataByTensor(kernel.input());
+ assert(input_data);
+
+ auto *output_data = runtime_graph->getDataByTensor(kernel.output());
+
+ bool is_inplace = runtime_graph->is_inplace_op(cur_op);
+
+ const auto options = cur_op->builtin_options_as_LeakyReluOptions();
+
+ switch (Tensor::element_type(kernel.input()))
{
+#ifndef DIS_FLOAT
case DataType::FLOAT32:
- evalFloat();
- break;
- case DataType::U8:
- evalQuantized();
+ {
+ const float *input_data_float = kernels::getTensorData<float>(input_data);
+ float *output_data_float = kernels::getTensorData<float>(output_data);
+ if (is_inplace)
+ {
+ output_data_float = const_cast<float *>(input_data_float);
+ }
+
+ assert(output_data_float);
+ const int flat_size =
+ kernels::getTensorRuntimeShape(kernel.input(), runtime_graph).flatSize();
+
+ luci_interpreter_pal::ReLUCommon(flat_size, input_data_float, output_data_float,
+ options->alpha(), false);
break;
+ }
+#endif // DIS_FLOAT
default:
- assert(false && "Unsupported type.");
+ assert(false && "Unsupported type");
}
-}
-
-void LeakyRelu::evalFloat() const
-{
- tflite::LeakyReluParams op_params{};
- op_params.alpha = params().alpha;
- luci_interpreter_pal::LeakyRelu(op_params, getTensorShape(input()), getTensorData<float>(input()),
- getTensorShape(output()), getTensorData<float>(output()));
-}
-void LeakyRelu::evalQuantized() const
-{
- tflite::LeakyReluParams op_params{};
- op_params.input_offset = input()->zero_point();
- op_params.output_offset = output()->zero_point();
- op_params.output_multiplier_alpha = _output_multiplier_alpha;
- op_params.output_shift_alpha = _output_shift_alpha;
- op_params.output_multiplier_identity = _output_multiplier_identity;
- op_params.output_shift_identity = _output_shift_identity;
-
- tflite::reference_ops::QuantizeLeakyRelu(
- op_params, getTensorShape(input()), getTensorData<uint8_t>(input()), getTensorShape(output()),
- getTensorData<uint8_t>(output()));
+ if (is_inplace)
+ runtime_graph->makeInplaceOperation(kernel.input(), kernel.output());
}
-
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/LeakyRelu.h b/onert-micro/luci-interpreter/src/kernels/LeakyRelu.h
deleted file mode 100644
index 88e8c0326..000000000
--- a/onert-micro/luci-interpreter/src/kernels/LeakyRelu.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_LEAKYRELU_H
-#define LUCI_INTERPRETER_KERNELS_LEAKYRELU_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class LeakyRelu : public KernelWithParams<LeakyReluParams>
-{
-public:
- LeakyRelu(const Tensor *input, Tensor *output, const LeakyReluParams &params);
-
- const Tensor *input() const { return _inputs[0]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-
-private:
- void evalFloat() const;
- void evalQuantized() const;
-
-private:
- int32_t _output_multiplier_alpha = 0;
- int _output_shift_alpha = 0;
- int32_t _output_multiplier_identity = 0;
- int _output_shift_identity = 0;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_LEAKYRELU_H
diff --git a/onert-micro/luci-interpreter/src/kernels/LeakyRelu.test.cpp b/onert-micro/luci-interpreter/src/kernels/LeakyRelu.test.cpp
index 6063fa5f2..049ba21fb 100644
--- a/onert-micro/luci-interpreter/src/kernels/LeakyRelu.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/LeakyRelu.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,114 +14,74 @@
* limitations under the License.
*/
-#include "kernels/LeakyRelu.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/leaky_relu/FloatLeakyReLUKernel.h"
+#include "luci_interpreter/test_models/leaky_relu/NegLeakyReLUKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
using namespace testing;
-template <typename T>
-void Check(std::initializer_list<int32_t> input_shape, std::initializer_list<int32_t> output_shape,
- std::initializer_list<float> input_data, std::initializer_list<float> output_data,
- float alpha)
+class LeakyReLUTest : public ::testing::Test
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- constexpr DataType element_type = getElementType<T>();
- Tensor input_tensor =
- makeInputTensor<element_type>(input_shape, input_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(element_type);
-
- LeakyReluParams params{};
- params.alpha = alpha;
-
- LeakyRelu kernel(&input_tensor, &output_tensor, params);
-
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
- EXPECT_THAT(extractTensorData<T>(output_tensor), ::testing::ElementsAreArray(output_data));
-}
+ // Do nothing
+};
-template <>
-void Check<uint8_t>(std::initializer_list<int32_t> input_shape,
- std::initializer_list<int32_t> output_shape,
- std::initializer_list<float> input_data,
- std::initializer_list<float> output_data, float alpha)
+template <typename T>
+std::vector<T> checkLeakyReLUKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- const float quantized_tolerance = getTolerance(-8, 127.f / 16.f, 255);
- std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(-8, 127.f / 16.f);
- Tensor input_tensor = makeInputTensor<DataType::U8>(
- input_shape, quant_param.first, quant_param.second, input_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.second);
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- LeakyReluParams params{};
- params.alpha = alpha;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- LeakyRelu kernel(&input_tensor, &output_tensor, params);
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
- EXPECT_THAT(dequantizeTensorData(output_tensor),
- FloatArrayNear(output_data, quantized_tolerance));
-}
+ runtime_module.execute();
-template <typename T> class LeakReluTest : public ::testing::Test
-{
-};
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
-using DataTypes = ::testing::Types<float, uint8_t>;
-TYPED_TEST_SUITE(LeakReluTest, DataTypes);
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
+}
-TYPED_TEST(LeakReluTest, Simple)
+TEST_F(LeakyReLUTest, Float_P)
{
- Check<TypeParam>(/*input_shape=*/{2, 3}, /*output_shape=*/{2, 3},
- /*input_data=*/
- {
- 0.0f, 1.0f, 3.0f, // Row 1
- 1.0f, -1.0f, -2.0f, // Row 2
- },
- /*output_data=*/
- {
- 0.0f, 1.0f, 3.0f, // Row 1
- 1.0f, -0.5f, -1.0f, // Row 2
- },
- /*alpha=*/0.5f);
-
- SUCCEED();
+ test_kernel::TestDataFloatLeakyReLU test_data_kernel;
+ std::vector<float> output_data_vector = checkLeakyReLUKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+ test_data_kernel.get_output_data_by_index(0), 0.0001f));
}
-TEST(LeakReluTest, IvalidInputOutputType_NEG)
+TEST_F(LeakyReLUTest, Input_output_type_mismatch_NEG)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({2, 3},
- {
- 0.0f, 1.0f, 3.0f, // Row 1
- 1.0f, -1.0f, -2.0f, // Row 2
- },
- memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U8);
-
- LeakyReluParams params{};
- params.alpha = 0.5f;
-
- LeakyRelu kernel(&input_tensor, &output_tensor, params);
-
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::NegTestDataInputOutputTypeMismatchLeakyReLUKernel test_data_kernel;
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Less.cpp b/onert-micro/luci-interpreter/src/kernels/Less.cpp
index 54a785ccd..4a688e463 100644
--- a/onert-micro/luci-interpreter/src/kernels/Less.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Less.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,128 +14,140 @@
* limitations under the License.
*/
-#include "kernels/Less.h"
+#include "Builders.h"
#include "kernels/Utils.h"
+#include "TISOKernel.h"
-#include <tensorflow/lite/kernels/internal/reference/comparisons.h>
+#include "PALComparisons.h"
namespace luci_interpreter
{
-namespace kernels
+namespace
{
+#ifndef DIS_QUANT
+void evalQuantized(const circle::Tensor *x, const circle::Tensor *y, const circle::Tensor *output,
+ BaseRuntimeGraph *runtime_graph)
+{
+ auto x_data = kernels::getTensorData<uint8_t>(runtime_graph->getDataByTensor(x));
+ if (x_data == nullptr)
+ x_data = kernels::getTensorData<uint8_t>(runtime_graph->getConstDataByTensor(x));
-Less::Less(const Tensor *x, const Tensor *y, Tensor *output) : Kernel({x, y}, {output}) {}
+ assert(x_data != nullptr);
-void Less::configure()
-{
- LUCI_INTERPRETER_CHECK(x()->element_type() == y()->element_type());
- LUCI_INTERPRETER_CHECK(output()->element_type() == DataType::BOOL);
+ auto y_data = kernels::getTensorData<uint8_t>(runtime_graph->getDataByTensor(y));
+ if (y_data == nullptr)
+ y_data = kernels::getTensorData<uint8_t>(runtime_graph->getConstDataByTensor(y));
- if (x()->element_type() == DataType::U8)
- {
- quantizeMultiplierSmallerThanOneExp(x()->scale(), &_x_multiplier, &_x_shift);
- quantizeMultiplierSmallerThanOneExp(y()->scale(), &_y_multiplier, &_y_shift);
- }
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(calculateShapeForBroadcast(x()->shape(), y()->shape()));
-}
+ assert(y_data != nullptr);
-void Less::execute() const
-{
- switch (x()->element_type())
- {
- case DataType::FLOAT32:
- evalFloat();
- break;
- case DataType::S64:
- evalInteger<int64_t>();
- break;
- case DataType::S32:
- evalInteger<int32_t>();
- break;
- case DataType::U8:
- evalQuantized();
- break;
- default:
- assert(false && "Unsupported type.");
- }
-}
+ auto output_data = kernels::getTensorData<bool>(runtime_graph->getDataByTensor(output));
-void Less::evalFloat() const
-{
- const auto x_data = getTensorData<float>(x());
- const auto y_data = getTensorData<float>(y());
- auto output_data = getTensorData<bool>(output());
+ int32_t x_multiplier;
+ int x_shift;
+
+ int32_t y_multiplier;
+ int y_shift;
- tflite::ComparisonParams op_params;
- op_params.is_broadcast = x()->shape() != y()->shape();
+ kernels::quantizeMultiplierSmallerThanOneExp(Tensor::scale(x), &x_multiplier, &x_shift);
+ kernels::quantizeMultiplierSmallerThanOneExp(Tensor::scale(y), &y_multiplier, &y_shift);
+
+ luci_interpreter_pal::ComparisonParams op_params;
+ op_params.left_shift = 8;
+ op_params.input1_offset = -Tensor::zero_point(x); // Note the '-'
+ op_params.input1_shift = x_shift;
+ op_params.input1_multiplier = x_multiplier;
+ op_params.input2_offset = -Tensor::zero_point(y); // Note the '-'
+ op_params.input2_shift = y_shift;
+ op_params.input2_multiplier = y_multiplier;
+ op_params.is_broadcast = Tensor::num_elements(x) != Tensor::num_elements(y);
if (op_params.is_broadcast)
{
- tflite::reference_ops::Broadcast4DSlowLess(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data,
- getTensorShape(output()), output_data);
+ luci_interpreter_pal::BroadcastComparison4DSlowWithScaling<uint8_t>(
+ op_params, kernels::getTensorShape(x), x_data, kernels::getTensorShape(y), y_data,
+ kernels::getTensorShape(output), output_data, luci_interpreter_pal::LessFn);
}
else
{
- tflite::reference_ops::Less(op_params, getTensorShape(x()), x_data, getTensorShape(y()), y_data,
- getTensorShape(output()), output_data);
+ const int64_t flat_size = kernels::getTensorShape(x).flatSize();
+ luci_interpreter_pal::ComparisonWithScaling<uint8_t>(op_params, flat_size, x_data, y_data,
+ output_data, luci_interpreter_pal::LessFn);
}
}
+#endif // DIS_QUANT
-template <typename T> void Less::evalInteger() const
+template <typename T>
+void evalGeneric(const circle::Tensor *x, const circle::Tensor *y, const circle::Tensor *output,
+ BaseRuntimeGraph *runtime_graph)
{
- const auto x_data = getTensorData<T>(x());
- const auto y_data = getTensorData<T>(y());
- auto output_data = getTensorData<bool>(output());
+ auto x_data = kernels::getTensorData<T>(runtime_graph->getDataByTensor(x));
+ if (x_data == nullptr)
+ x_data = kernels::getTensorData<T>(runtime_graph->getConstDataByTensor(x));
- tflite::ComparisonParams op_params;
- op_params.is_broadcast = x()->shape() != y()->shape();
+ assert(x_data != nullptr);
+
+ auto y_data = kernels::getTensorData<T>(runtime_graph->getDataByTensor(y));
+ if (y_data == nullptr)
+ y_data = kernels::getTensorData<T>(runtime_graph->getConstDataByTensor(y));
+
+ assert(y_data != nullptr);
+
+ auto output_data = kernels::getTensorData<bool>(runtime_graph->getDataByTensor(output));
+
+ luci_interpreter_pal::ComparisonParams op_params;
+ op_params.is_broadcast = Tensor::num_elements(x) != Tensor::num_elements(y);
if (op_params.is_broadcast)
{
- tflite::reference_ops::Broadcast4DSlowLessNoScaling(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data,
- getTensorShape(output()), output_data);
+ luci_interpreter_pal::BroadcastComparison4DSlowNoScaling<T>(
+ op_params, kernels::getTensorShape(x), x_data, kernels::getTensorShape(y), y_data,
+ kernels::getTensorShape(output), output_data, luci_interpreter_pal::LessFn);
}
else
{
- tflite::reference_ops::LessNoScaling(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data, getTensorShape(output()),
- output_data);
+ const int64_t flat_size = kernels::getTensorShape(x).flatSize();
+ luci_interpreter_pal::ComparisonNoScaling<T>(flat_size, x_data, y_data, output_data,
+ luci_interpreter_pal::LessFn);
}
}
-void Less::evalQuantized() const
+} // namespace
+
+void configure_kernel_CircleLess(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- const auto x_data = getTensorData<uint8_t>(x());
- const auto y_data = getTensorData<uint8_t>(y());
- auto output_data = getTensorData<bool>(output());
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
- tflite::ComparisonParams op_params;
- op_params.left_shift = 8;
- op_params.input1_offset = -x()->zero_point(); // Note the '-'
- op_params.input1_shift = _x_shift;
- op_params.input1_multiplier = _x_multiplier;
- op_params.input2_offset = -y()->zero_point(); // Note the '-'
- op_params.input2_shift = _y_shift;
- op_params.input2_multiplier = _y_multiplier;
- op_params.is_broadcast = x()->shape() != y()->shape();
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+ Tensor::element_type(kernel.input2()));
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.output()) == DataType::BOOL);
+}
- if (op_params.is_broadcast)
- {
- tflite::reference_ops::Broadcast4DSlowLessWithScaling(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data,
- getTensorShape(output()), output_data);
- }
- else
+void execute_kernel_CircleLess(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
+
+ switch (Tensor::element_type(kernel.input1()))
{
- tflite::reference_ops::LessWithScaling(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data, getTensorShape(output()),
- output_data);
+ case DataType::S64:
+ evalGeneric<int64_t>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+ break;
+ case DataType::S32:
+ evalGeneric<int32_t>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+ break;
+#ifndef DIS_QUANT
+ case DataType::U8:
+ evalQuantized(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+ break;
+#endif // DIS_QUANT
+#ifndef DIS_FLOAT
+ case DataType::FLOAT32:
+ evalGeneric<float>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+ break;
+#endif // DIS_FLOAT
+ default:
+ assert(false && "Unsupported type.");
}
}
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Less.test.cpp b/onert-micro/luci-interpreter/src/kernels/Less.test.cpp
index 8c5963363..08279e9d1 100644
--- a/onert-micro/luci-interpreter/src/kernels/Less.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Less.test.cpp
@@ -15,14 +15,16 @@
* limitations under the License.
*/
-#include "kernels/Less.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/less/FloatLessKernel.h"
+#include "luci_interpreter/test_models/less/IntLessKernel.h"
+#include "luci_interpreter/test_models/less/QuantLessKernel.h"
+#include "luci_interpreter/test_models/less/NegTestDataLessKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
@@ -30,305 +32,134 @@ using namespace testing;
class LessTest : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-TEST_F(LessTest, FloatSimple)
+template <typename T, typename U>
+std::vector<U> checkLessKernel(test_kernel::TestDataBase<T, U> *test_data_base)
{
- std::vector<float> x_data{
- 0.5, 0.7, 0.9, // Row 1
- 1, 0, -1, // Row 2
- };
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- std::vector<float> y_data{
- 0.9, 0.7, 0.5, // Row 1
- -1, 0, 1, // Row 2
- };
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- std::vector<bool> ref_output_data{
- true, false, false, // Row 1
- false, false, true, // Row 2
- };
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 2);
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
+ // set left input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
- Less kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ // set right input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(1));
+ std::copy(test_data_base->get_input_data_by_index(1).begin(),
+ test_data_base->get_input_data_by_index(1).end(), input_tensor_data);
+ }
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({2, 3}));
-}
-
-TEST_F(LessTest, FloatBroardcast)
-{
- std::vector<float> x_data{
- 0.5, 0.7, 0.9, // Row 1
- 1, 0, -1, // Row 2
- -1, 0, 1, // Row 3
- };
+ runtime_module.execute();
- std::vector<float> y_data{
- 0.9, 0.7, 0.5, // Row 1
- };
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
- std::vector<bool> ref_output_data{
- true, false, false, // Row 1
- false, true, true, // Row 2
- true, true, false, // Row 3
- };
-
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({3, 3}, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({1, 3}, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Less kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({3, 3}));
+ U *output_data = reinterpret_cast<U *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(U));
+ std::vector<U> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-template <loco::DataType DType>
-void checkIntegerSimple(luci_interpreter::IMemoryManager *memory_manager)
+TEST_F(LessTest, FloatNoBroadcast_P)
{
- using dtype = typename loco::DataTypeImpl<DType>::Type;
- dtype min_value = std::numeric_limits<dtype>::min();
- dtype max_value = std::numeric_limits<dtype>::max();
- std::vector<dtype> x_data{min_value, 2, max_value};
-
- std::vector<dtype> y_data{min_value + 1, -2, max_value};
-
- std::vector<bool> ref_output_data{true, false, false};
-
- Tensor x_tensor = makeInputTensor<DType>({3}, x_data, memory_manager);
- Tensor y_tensor = makeInputTensor<DType>({3}, y_data, memory_manager);
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Less kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({3}));
+ const bool is_with_broadcast = false;
+ test_kernel::TestDataFloatLess test_data_kernel(is_with_broadcast, false);
+ std::vector<bool> output_data_vector = checkLessKernel<float, bool>(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-template <loco::DataType DType>
-void checkIntegerBroadcast(luci_interpreter::IMemoryManager *memory_manager)
+TEST_F(LessTest, FloatWithBroadcast_P)
{
- using dtype = typename loco::DataTypeImpl<DType>::Type;
- dtype min_value = std::numeric_limits<dtype>::min();
- dtype max_value = std::numeric_limits<dtype>::max();
- std::vector<dtype> x_data{
- min_value, 2, 3, // Row 1
- 4, 5, max_value, // Row 2
- -1, -4, -3, // Row 3
- min_value, -2, max_value, // Row 4
- };
-
- std::vector<dtype> y_data{
- min_value + 1, -2, max_value - 1, // Row 1
- };
-
- std::vector<bool> ref_output_data{
- true, false, true, // Row 1
- false, false, false, // Row 2
- false, true, true, // Row 3
- true, false, false, // Row 4
- };
-
- Tensor x_tensor = makeInputTensor<DType>({4, 3}, x_data, memory_manager);
- Tensor y_tensor = makeInputTensor<DType>({3}, y_data, memory_manager);
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Less kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({4, 3}));
+ const bool is_with_broadcast = true;
+ test_kernel::TestDataFloatLess test_data_kernel(is_with_broadcast, false);
+ std::vector<bool> output_data_vector = checkLessKernel<float, bool>(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-TEST_F(LessTest, Int32)
+TEST_F(LessTest, FloatNoBroadcast_NEG)
{
- checkIntegerSimple<loco::DataType::S32>(_memory_manager.get());
- checkIntegerBroadcast<loco::DataType::S32>(_memory_manager.get());
- SUCCEED();
+ const bool is_with_broadcast = false;
+ test_kernel::TestDataFloatLess test_data_kernel(is_with_broadcast, true);
+ EXPECT_DEATH(checkLessKernel(&test_data_kernel), "");
}
-TEST_F(LessTest, Int64)
+TEST_F(LessTest, FloatWithBroadcast_NEG)
{
- checkIntegerSimple<loco::DataType::S64>(_memory_manager.get());
- checkIntegerBroadcast<loco::DataType::S64>(_memory_manager.get());
- SUCCEED();
+ const bool is_with_broadcast = true;
+ test_kernel::TestDataFloatLess test_data_kernel(is_with_broadcast, true);
+ EXPECT_DEATH(checkLessKernel(&test_data_kernel), "");
}
-// Choose min / max in such a way that there are exactly 256 units to avoid rounding errors.
-const float F_MIN = -128.0 / 128.0;
-const float F_MAX = 127.0 / 128.0;
-
-TEST_F(LessTest, Uint8Quantized)
+TEST_F(LessTest, IntWithBroadcast_P)
{
- std::vector<float> x_data{
- 0.5, 0.6, 0.7, 0.9, // Row 1
- 1, 0, 0.05, -1, // Row 2
- };
-
- std::vector<float> y_data{
- 0.9, 0.6, 0.55, 0.5, // Row 1
- -1, 0.05, 0, 1, // Row 2
- };
-
- std::vector<bool> ref_output_data{
- true, false, false, false, // Row 1
- false, true, false, true, // Row 2
- };
-
- std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
- Tensor x_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, quant_param.first, quant_param.second, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, quant_param.first, quant_param.second, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Less kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 4, 1}));
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
+ const bool is_with_broadcast = true;
+ test_kernel::TestDataIntLess test_data_kernel(is_with_broadcast, false);
+ std::vector<bool> output_data_vector = checkLessKernel<int32_t, bool>(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-TEST_F(LessTest, Uint8QuantizedRescale)
+TEST_F(LessTest, IntNoBroadcast_P)
{
- std::vector<float> x_data{
- 0.5, 0.6, 0.7, 0.9, // Row 1
- 1, 0, 0.05, -1, // Row 2
- };
-
- std::vector<float> y_data{
- 0.9, 0.6, 0.6, 0.5, // Row 1
- -1, 0.05, 0, 1, // Row 2
- };
-
- std::vector<bool> ref_output_data{
- true, false, false, false, // Row 1
- false, true, false, true, // Row 2
- };
-
- std::pair<float, int32_t> x_quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
- std::pair<float, int32_t> y_quant_param = quantizationParams<uint8_t>(F_MIN * 1.2, F_MAX * 1.5);
-
- Tensor x_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, x_quant_param.first, x_quant_param.second, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, y_quant_param.first, y_quant_param.second, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Less kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 4, 1}));
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
+ const bool is_with_broadcast = false;
+ test_kernel::TestDataIntLess test_data_kernel(is_with_broadcast, false);
+ std::vector<bool> output_data_vector = checkLessKernel<int32_t, bool>(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-TEST_F(LessTest, Uint8QuantizedBroadcast)
+TEST_F(LessTest, IntWithBroadcast_NEG)
{
- std::vector<float> x_data{
- 0.4, -0.8, 0.7, 0.3, // Row 1
- -0.5, 0.1, 0, 0.5, // Row 2
- 1, 0, 0.05, -1, // Row 3
- };
-
- std::vector<float> y_data{
- -1, 0.05, 0, 1, // Row 1
- };
-
- std::vector<bool> ref_output_data{
- false, true, false, true, // Row 1
- false, false, false, true, // Row 2
- false, true, false, true, // Row 3
- };
-
- std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
- Tensor x_tensor = makeInputTensor<DataType::U8>(
- {1, 3, 4, 1}, quant_param.first, quant_param.second, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::U8>(
- {1, 1, 4, 1}, quant_param.first, quant_param.second, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Less kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 3, 4, 1}));
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
-}
-
-TEST_F(LessTest, Input_Type_Mismatch_NEG)
-{
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::U8>({1}, {1}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Less kernel(&x_tensor, &y_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
+ const bool is_with_broadcast = true;
+ test_kernel::TestDataIntLess test_data_kernel(is_with_broadcast, true);
+ EXPECT_DEATH(checkLessKernel(&test_data_kernel), "");
}
-TEST_F(LessTest, Input_Output_Type_NEG)
+TEST_F(LessTest, IntNoBroadcast_NEG)
{
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- Less kernel(&x_tensor, &y_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
+ const bool is_with_broadcast = false;
+ test_kernel::TestDataIntLess test_data_kernel(is_with_broadcast, true);
+ EXPECT_DEATH(checkLessKernel(&test_data_kernel), "");
}
-TEST_F(LessTest, Float_Broadcast_NEG)
+TEST_F(LessTest, Quant_P)
{
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({2}, {1.f, 2.f}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({3}, {1.f, 2.f, 3.f}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Less kernel(&x_tensor, &y_tensor, &output_tensor);
- ASSERT_ANY_THROW(kernel.configure());
+ const bool is_with_broadcast = false;
+ test_kernel::TestDataQuantLess test_data_kernel(is_with_broadcast, false);
+ std::vector<bool> output_data_vector = checkLessKernel<uint8_t, bool>(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-TEST_F(LessTest, Int32_Broadcast_NEG)
+TEST_F(LessTest, Quant_NEG)
{
- Tensor x_tensor = makeInputTensor<DataType::S32>({2}, {1, 2}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::S32>({3}, {1, 2, 3}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- Less kernel(&x_tensor, &y_tensor, &output_tensor);
- ASSERT_ANY_THROW(kernel.configure());
+ const bool is_with_broadcast = false;
+ test_kernel::TestDataQuantLess test_data_kernel(is_with_broadcast, true);
+ EXPECT_DEATH(checkLessKernel(&test_data_kernel), "");
}
-TEST_F(LessTest, Int64_Broadcast_NEG)
+TEST_F(LessTest, Wrong_Output_Type_NEG)
{
- Tensor x_tensor = makeInputTensor<DataType::S64>({2}, {1, 2}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::S64>({3}, {1, 2, 3}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
+ test_kernel::NegTestDataLessKernel test_data_kernel;
- Less kernel(&x_tensor, &y_tensor, &output_tensor);
- ASSERT_ANY_THROW(kernel.configure());
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/LessEqual.cpp b/onert-micro/luci-interpreter/src/kernels/LessEqual.cpp
index 03b122acb..8928ba4e1 100644
--- a/onert-micro/luci-interpreter/src/kernels/LessEqual.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/LessEqual.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,128 +14,76 @@
* limitations under the License.
*/
-#include "kernels/LessEqual.h"
+#include "Builders.h"
#include "kernels/Utils.h"
+#include "TISOKernel.h"
-#include <tensorflow/lite/kernels/internal/reference/comparisons.h>
+#include "PALComparisons.h"
namespace luci_interpreter
{
-namespace kernels
+namespace
{
+// TODO: reduce code duplication with less
+template <typename T>
+void evalGeneric(const circle::Tensor *x, const circle::Tensor *y, const circle::Tensor *output,
+ BaseRuntimeGraph *runtime_graph)
+{
+ auto x_data = kernels::getTensorData<T>(runtime_graph->getDataByTensor(x));
+ if (x_data == nullptr)
+ x_data = kernels::getTensorData<T>(runtime_graph->getConstDataByTensor(x));
+
+ assert(x_data != nullptr);
+
+ auto y_data = kernels::getTensorData<T>(runtime_graph->getDataByTensor(y));
+ if (y_data == nullptr)
+ y_data = kernels::getTensorData<T>(runtime_graph->getConstDataByTensor(y));
+
+ assert(y_data != nullptr);
+
+ auto output_data = kernels::getTensorData<bool>(runtime_graph->getDataByTensor(output));
-LessEqual::LessEqual(const Tensor *x, const Tensor *y, Tensor *output) : Kernel({x, y}, {output}) {}
+ luci_interpreter_pal::ComparisonParams op_params;
+ op_params.is_broadcast = Tensor::num_elements(x) != Tensor::num_elements(y);
-void LessEqual::configure()
+ const int64_t flat_size = kernels::getTensorShape(x).flatSize();
+ luci_interpreter_pal::ComparisonNoScaling<T>(flat_size, x_data, y_data, output_data,
+ luci_interpreter_pal::LessEqualFn);
+}
+
+} // namespace
+
+void configure_kernel_CircleLessEqual(const circle::Operator *cur_op,
+ BaseRuntimeGraph *runtime_graph)
{
- LUCI_INTERPRETER_CHECK(x()->element_type() == y()->element_type());
- LUCI_INTERPRETER_CHECK(output()->element_type() == DataType::BOOL);
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
- if (x()->element_type() == DataType::U8)
- {
- quantizeMultiplierSmallerThanOneExp(x()->scale(), &_x_multiplier, &_x_shift);
- quantizeMultiplierSmallerThanOneExp(y()->scale(), &_y_multiplier, &_y_shift);
- }
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(calculateShapeForBroadcast(x()->shape(), y()->shape()));
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+ Tensor::element_type(kernel.input2()));
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.output()) == DataType::BOOL);
}
-void LessEqual::execute() const
+void execute_kernel_CircleLessEqual(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- switch (x()->element_type())
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
+
+ switch (Tensor::element_type(kernel.input1()))
{
- case DataType::FLOAT32:
- evalFloat();
- break;
case DataType::S64:
- evalInteger<int64_t>();
+ evalGeneric<int64_t>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
break;
case DataType::S32:
- evalInteger<int32_t>();
+ evalGeneric<int32_t>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
break;
- case DataType::U8:
- evalQuantized();
+#ifndef DIS_FLOAT
+ case DataType::FLOAT32:
+ evalGeneric<float>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
break;
+#endif // DIS_FLOAT
default:
assert(false && "Unsupported type.");
}
}
-void LessEqual::evalFloat() const
-{
- const auto x_data = getTensorData<float>(x());
- const auto y_data = getTensorData<float>(y());
- auto output_data = getTensorData<bool>(output());
-
- tflite::ComparisonParams op_params;
- op_params.is_broadcast = x()->shape() != y()->shape();
-
- if (op_params.is_broadcast)
- {
- tflite::reference_ops::Broadcast4DSlowLessEqual(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data,
- getTensorShape(output()), output_data);
- }
- else
- {
- tflite::reference_ops::LessEqual(op_params, getTensorShape(x()), x_data, getTensorShape(y()),
- y_data, getTensorShape(output()), output_data);
- }
-}
-
-template <typename T> void LessEqual::evalInteger() const
-{
- const auto x_data = getTensorData<T>(x());
- const auto y_data = getTensorData<T>(y());
- auto output_data = getTensorData<bool>(output());
-
- tflite::ComparisonParams op_params;
- op_params.is_broadcast = x()->shape() != y()->shape();
-
- if (op_params.is_broadcast)
- {
- tflite::reference_ops::Broadcast4DSlowLessEqualNoScaling(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data,
- getTensorShape(output()), output_data);
- }
- else
- {
- tflite::reference_ops::LessEqualNoScaling(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data, getTensorShape(output()),
- output_data);
- }
-}
-
-void LessEqual::evalQuantized() const
-{
- const auto x_data = getTensorData<uint8_t>(x());
- const auto y_data = getTensorData<uint8_t>(y());
- auto output_data = getTensorData<bool>(output());
-
- tflite::ComparisonParams op_params;
- op_params.left_shift = 8;
- op_params.input1_offset = -x()->zero_point(); // Note the '-'
- op_params.input1_shift = _x_shift;
- op_params.input1_multiplier = _x_multiplier;
- op_params.input2_offset = -y()->zero_point(); // Note the '-'
- op_params.input2_shift = _y_shift;
- op_params.input2_multiplier = _y_multiplier;
- op_params.is_broadcast = x()->shape() != y()->shape();
-
- if (op_params.is_broadcast)
- {
- tflite::reference_ops::Broadcast4DSlowLessEqualWithScaling(
- op_params, getTensorShape(x()), x_data, getTensorShape(y()), y_data, getTensorShape(output()),
- output_data);
- }
- else
- {
- tflite::reference_ops::LessEqualWithScaling(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data,
- getTensorShape(output()), output_data);
- }
-}
-
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/LessEqual.h b/onert-micro/luci-interpreter/src/kernels/LessEqual.h
deleted file mode 100644
index 93da8567c..000000000
--- a/onert-micro/luci-interpreter/src/kernels/LessEqual.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_LESS_EQUAL_H
-#define LUCI_INTERPRETER_KERNELS_LESS_EQUAL_H
-
-#include "core/Kernel.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class LessEqual : public Kernel
-{
-public:
- LessEqual(const Tensor *x, const Tensor *y, Tensor *output);
-
- const Tensor *x() const { return _inputs[0]; }
- const Tensor *y() const { return _inputs[1]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-
-private:
- void evalFloat() const;
- template <typename T> void evalInteger() const;
- void evalQuantized() const;
-
-private:
- int32_t _x_multiplier = 0;
- int _x_shift = 0;
- int32_t _y_multiplier = 0;
- int _y_shift = 0;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_LESS_EQUAL_H
diff --git a/onert-micro/luci-interpreter/src/kernels/LessEqual.test.cpp b/onert-micro/luci-interpreter/src/kernels/LessEqual.test.cpp
index b2e2fa7a1..e53dc05a4 100644
--- a/onert-micro/luci-interpreter/src/kernels/LessEqual.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/LessEqual.test.cpp
@@ -15,14 +15,13 @@
* limitations under the License.
*/
-#include "kernels/LessEqual.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/less_equal/FloatLessEqualKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
@@ -30,305 +29,61 @@ using namespace testing;
class LessEqualTest : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-TEST_F(LessEqualTest, FloatSimple)
-{
- std::vector<float> x_data{
- 0.5, 0.7, 0.9, // Row 1
- 1, 0, -1, // Row 2
- };
-
- std::vector<float> y_data{
- 0.9, 0.7, 0.5, // Row 1
- -1, 0, 1, // Row 2
- };
-
- std::vector<bool> ref_output_data{
- true, true, false, // Row 1
- false, true, true, // Row 2
- };
-
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({2, 3}));
-}
-
-TEST_F(LessEqualTest, FloatBroardcast)
-{
- std::vector<float> x_data{
- 0.5, 0.7, 0.9, // Row 1
- 1, 0, -1, // Row 2
- -1, 0, 1, // Row 3
- };
-
- std::vector<float> y_data{
- 0.9, 0.7, 0.5, // Row 1
- };
-
- std::vector<bool> ref_output_data{
- true, true, false, // Row 1
- false, true, true, // Row 2
- true, true, false, // Row 3
- };
-
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({3, 3}, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({1, 3}, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({3, 3}));
-}
-
-template <loco::DataType DType>
-void checkIntegerSimple(luci_interpreter::IMemoryManager *memory_manager)
+template <typename T, typename U>
+std::vector<U> checkLessEqualKernel(test_kernel::TestDataBase<T, U> *test_data_base)
{
- using dtype = typename loco::DataTypeImpl<DType>::Type;
- dtype min_value = std::numeric_limits<dtype>::min();
- dtype max_value = std::numeric_limits<dtype>::max();
- std::vector<dtype> x_data{min_value, 2, max_value};
-
- std::vector<dtype> y_data{min_value + 1, -2, max_value};
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- std::vector<bool> ref_output_data{true, false, true};
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- Tensor x_tensor = makeInputTensor<DType>({3}, x_data, memory_manager);
- Tensor y_tensor = makeInputTensor<DType>({3}, y_data, memory_manager);
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 2);
- LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ // set left input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({3}));
-}
-
-template <loco::DataType DType>
-void checkIntegerBroadcast(luci_interpreter::IMemoryManager *memory_manager)
-{
- using dtype = typename loco::DataTypeImpl<DType>::Type;
- dtype min_value = std::numeric_limits<dtype>::min();
- dtype max_value = std::numeric_limits<dtype>::max();
- std::vector<dtype> x_data{
- min_value, 2, 3, // Row 1
- 4, 5, max_value, // Row 2
- -1, -4, -3, // Row 3
- min_value, -2, max_value, // Row 4
- };
+ // set right input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(1));
+ std::copy(test_data_base->get_input_data_by_index(1).begin(),
+ test_data_base->get_input_data_by_index(1).end(), input_tensor_data);
+ }
- std::vector<dtype> y_data{
- min_value + 1, -2, max_value - 1, // Row 1
- };
+ runtime_module.execute();
- std::vector<bool> ref_output_data{
- true, false, true, // Row 1
- false, false, false, // Row 2
- false, true, true, // Row 3
- true, true, false, // Row 4
- };
-
- Tensor x_tensor = makeInputTensor<DType>({4, 3}, x_data, memory_manager);
- Tensor y_tensor = makeInputTensor<DType>({3}, y_data, memory_manager);
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({4, 3}));
-}
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
-TEST_F(LessEqualTest, Int32)
-{
- checkIntegerSimple<loco::DataType::S32>(_memory_manager.get());
- checkIntegerBroadcast<loco::DataType::S32>(_memory_manager.get());
- SUCCEED();
+ U *output_data = reinterpret_cast<U *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(U));
+ std::vector<U> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST_F(LessEqualTest, Int64)
+TEST_F(LessEqualTest, FloatNoBroadcast_P)
{
- checkIntegerSimple<loco::DataType::S64>(_memory_manager.get());
- checkIntegerBroadcast<loco::DataType::S64>(_memory_manager.get());
- SUCCEED();
+ const bool is_with_broadcast = false;
+ test_kernel::TestDataFloatLessEqual test_data_kernel(is_with_broadcast, false);
+ std::vector<bool> output_data_vector = checkLessEqualKernel<float, bool>(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-// Choose min / max in such a way that there are exactly 256 units to avoid rounding errors.
-const float F_MIN = -128.0 / 128.0;
-const float F_MAX = 127.0 / 128.0;
-
-TEST_F(LessEqualTest, Uint8Quantized)
+TEST_F(LessEqualTest, FloatNoBroadcast_NEG)
{
- std::vector<float> x_data{
- 0.5, 0.6, 0.7, 0.9, // Row 1
- 1, 0, 0.05, -1, // Row 2
- };
-
- std::vector<float> y_data{
- 0.9, 0.6, 0.55, 0.5, // Row 1
- -1, 0.05, 0, 1, // Row 2
- };
-
- std::vector<bool> ref_output_data{
- true, true, false, false, // Row 1
- false, true, false, true, // Row 2
- };
-
- std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
- Tensor x_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, quant_param.first, quant_param.second, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, quant_param.first, quant_param.second, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 4, 1}));
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
-}
-
-TEST_F(LessEqualTest, Uint8QuantizedRescale)
-{
- std::vector<float> x_data{
- 0.5, 0.6, 0.7, 0.9, // Row 1
- 1, 0, 0.05, -1, // Row 2
- };
-
- std::vector<float> y_data{
- 0.9, 0.6, 0.6, 0.5, // Row 1
- -1, 0.05, 0, 1, // Row 2
- };
-
- std::vector<bool> ref_output_data{
- true, true, false, false, // Row 1
- false, true, false, true, // Row 2
- };
-
- std::pair<float, int32_t> x_quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
- std::pair<float, int32_t> y_quant_param = quantizationParams<uint8_t>(F_MIN * 1.2, F_MAX * 1.5);
-
- Tensor x_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, x_quant_param.first, x_quant_param.second, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, y_quant_param.first, y_quant_param.second, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 4, 1}));
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
-}
-
-TEST_F(LessEqualTest, Uint8QuantizedBroadcast)
-{
- std::vector<float> x_data{
- 0.4, -0.8, 0.7, 0.3, // Row 1
- -0.5, 0.1, 0, 0.5, // Row 2
- 1, 0, 0.05, -1, // Row 3
- };
-
- std::vector<float> y_data{
- -1, 0.05, 0, 1, // Row 1
- };
-
- std::vector<bool> ref_output_data{
- false, true, false, true, // Row 1
- false, false, true, true, // Row 2
- false, true, false, true, // Row 3
- };
-
- std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
- Tensor x_tensor = makeInputTensor<DataType::U8>(
- {1, 3, 4, 1}, quant_param.first, quant_param.second, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::U8>(
- {1, 1, 4, 1}, quant_param.first, quant_param.second, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 3, 4, 1}));
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
-}
-
-TEST_F(LessEqualTest, Input_Type_Mismatch_NEG)
-{
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::U8>({1}, {1}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(LessEqualTest, Input_Output_Type_NEG)
-{
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(LessEqualTest, Float_Broadcast_NEG)
-{
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({2}, {1.f, 2.f}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({3}, {1.f, 2.f, 3.f}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- ASSERT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(LessEqualTest, Int32_Broadcast_NEG)
-{
- Tensor x_tensor = makeInputTensor<DataType::S32>({2}, {1, 2}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::S32>({3}, {1, 2, 3}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- ASSERT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(LessEqualTest, Int64_Broadcast_NEG)
-{
- Tensor x_tensor = makeInputTensor<DataType::S64>({2}, {1, 2}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::S64>({3}, {1, 2, 3}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- ASSERT_ANY_THROW(kernel.configure());
+ const bool is_with_broadcast = false;
+ test_kernel::TestDataFloatLessEqual test_data_kernel(is_with_broadcast, true);
+ EXPECT_DEATH(checkLessEqualKernel(&test_data_kernel), "");
}
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/LocalResponseNormalization.cpp b/onert-micro/luci-interpreter/src/kernels/LocalResponseNormalization.cpp
index 49a9eee3c..bf08db0a3 100644
--- a/onert-micro/luci-interpreter/src/kernels/LocalResponseNormalization.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/LocalResponseNormalization.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/LocalResponseNormalization.h b/onert-micro/luci-interpreter/src/kernels/LocalResponseNormalization.h
index 16b6ba4cb..60408a104 100644
--- a/onert-micro/luci-interpreter/src/kernels/LocalResponseNormalization.h
+++ b/onert-micro/luci-interpreter/src/kernels/LocalResponseNormalization.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/LogSoftmax.cpp b/onert-micro/luci-interpreter/src/kernels/LogSoftmax.cpp
index d5f99178a..b467cb06b 100644
--- a/onert-micro/luci-interpreter/src/kernels/LogSoftmax.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/LogSoftmax.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/LogSoftmax.h b/onert-micro/luci-interpreter/src/kernels/LogSoftmax.h
index 26c5dc3e2..18477fbe3 100644
--- a/onert-micro/luci-interpreter/src/kernels/LogSoftmax.h
+++ b/onert-micro/luci-interpreter/src/kernels/LogSoftmax.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/LogicalAnd.cpp b/onert-micro/luci-interpreter/src/kernels/LogicalAnd.cpp
index 65e0b5053..7e440cca4 100644
--- a/onert-micro/luci-interpreter/src/kernels/LogicalAnd.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/LogicalAnd.cpp
@@ -14,50 +14,58 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-#include "kernels/LogicalAnd.h"
-
+#include "Builders.h"
#include "kernels/Utils.h"
+#include "TISOKernel.h"
-#include "kernels/BinaryOpCommon.h"
+#include "PALLogicalCommon.h"
namespace luci_interpreter
{
-namespace kernels
+namespace
{
+bool LogicalAnd(bool x, bool y) { return x && y; }
+} // namespace
-LogicalAnd::LogicalAnd(const Tensor *input1, const Tensor *input2, Tensor *output)
- : Kernel({input1, input2}, {output})
+void configure_kernel_CircleLogicalAnd(const circle::Operator *cur_op,
+ BaseRuntimeGraph *runtime_graph)
{
-}
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
-void LogicalAnd::configure()
-{
- LUCI_INTERPRETER_CHECK(input1()->element_type() == input2()->element_type());
- LUCI_INTERPRETER_CHECK(input1()->element_type() == output()->element_type());
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(calculateShapeForBroadcast(input1()->shape(), input2()->shape()));
-}
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+ Tensor::element_type(kernel.input2()));
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) == DataType::BOOL);
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.output()) == DataType::BOOL);
-void LogicalAnd::execute() const
-{
- switch (input1()->element_type())
- {
- case DataType::BOOL:
- evalLogicalAnd();
- break;
- default:
- assert(false && "Unsupported type.");
- }
+ // TODO support broadcast
+ LUCI_INTERPRETER_CHECK(Tensor::num_elements(kernel.input1()) ==
+ Tensor::num_elements(kernel.input2()));
+ LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.input1()) == Tensor::num_dims(kernel.input2()));
}
-inline void LogicalAnd::evalLogicalAnd() const
+// TODO: add inplace
+// TODO: reduce code duplication with LogicalOr
+void execute_kernel_CircleLogicalAnd(const circle::Operator *cur_op,
+ BaseRuntimeGraph *runtime_graph)
{
- BinaryOpBroadcastSlow(getTensorShape(input1()), getTensorData<bool>(input1()),
- getTensorShape(input2()), getTensorData<bool>(input2()),
- getTensorShape(output()), getTensorData<bool>(output()),
- [](bool x, bool y) { return x && y; });
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
+
+ auto x_data = kernels::getTensorData<bool>(runtime_graph->getDataByTensor(kernel.input1()));
+ if (x_data == nullptr)
+ x_data = kernels::getTensorData<bool>(runtime_graph->getConstDataByTensor(kernel.input1()));
+
+ assert(x_data != nullptr);
+
+ auto y_data = kernels::getTensorData<bool>(runtime_graph->getDataByTensor(kernel.input2()));
+ if (y_data == nullptr)
+ y_data = kernels::getTensorData<bool>(runtime_graph->getConstDataByTensor(kernel.input2()));
+
+ assert(y_data != nullptr);
+
+ auto output_data = kernels::getTensorData<bool>(runtime_graph->getDataByTensor(kernel.output()));
+
+ const int64_t flat_size = kernels::getTensorShape(kernel.input1()).flatSize();
+ luci_interpreter_pal::LogicalCommon(flat_size, x_data, y_data, output_data, LogicalAnd);
}
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/LogicalAnd.h b/onert-micro/luci-interpreter/src/kernels/LogicalAnd.h
deleted file mode 100644
index 2609b31a2..000000000
--- a/onert-micro/luci-interpreter/src/kernels/LogicalAnd.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_LOGICALAND_H
-#define LUCI_INTERPRETER_KERNELS_LOGICALAND_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class LogicalAnd : public Kernel
-{
-public:
- LogicalAnd(const Tensor *input1, const Tensor *input2, Tensor *output);
-
- const Tensor *input1() const { return _inputs[0]; }
- const Tensor *input2() const { return _inputs[1]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-
-private:
- inline void evalLogicalAnd() const;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_LOGICALAND_H
diff --git a/onert-micro/luci-interpreter/src/kernels/LogicalAnd.test.cpp b/onert-micro/luci-interpreter/src/kernels/LogicalAnd.test.cpp
index 21b7951e0..2f72c0832 100644
--- a/onert-micro/luci-interpreter/src/kernels/LogicalAnd.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/LogicalAnd.test.cpp
@@ -15,14 +15,14 @@
* limitations under the License.
*/
-#include "kernels/LogicalAnd.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/logical_and/BoolLogicalAndKernel.h"
+#include "luci_interpreter/test_models/logical_and/NegLogicalAndKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
@@ -30,72 +30,66 @@ using namespace testing;
class LogicalAndTest : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-TEST_F(LogicalAndTest, Basic)
+template <typename T>
+std::vector<T> checkLogicalAndKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- Shape input_shape{1, 1, 1, 4};
- Tensor input_tensor1 =
- makeInputTensor<DataType::BOOL>(input_shape, {true, false, false, true}, _memory_manager.get());
- Tensor input_tensor2 =
- makeInputTensor<DataType::BOOL>(input_shape, {true, false, true, false}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- LogicalAnd kernel(&input_tensor1, &input_tensor2, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<bool>(output_tensor),
- ::testing::ElementsAre(true, false, false, false));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAre(1, 1, 1, 4));
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
+
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 2);
+
+ // set left input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
+
+ // set right input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(1));
+ std::copy(test_data_base->get_input_data_by_index(1).begin(),
+ test_data_base->get_input_data_by_index(1).end(), input_tensor_data);
+ }
+
+ runtime_module.execute();
+
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
+
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST_F(LogicalAndTest, Broadcast)
+TEST_F(LogicalAndTest, Bool_P)
{
- Tensor input_tensor1 = makeInputTensor<DataType::BOOL>({1, 1, 1, 4}, {true, false, false, true},
- _memory_manager.get());
- Tensor input_tensor2 =
- makeInputTensor<DataType::BOOL>({1, 1, 1, 1}, {true}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- LogicalAnd kernel(&input_tensor1, &input_tensor2, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<bool>(output_tensor),
- ::testing::ElementsAre(true, false, false, true));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAre(1, 1, 1, 4));
+ test_kernel::TestDataBoolLogicalAnd test_data_kernel;
+ std::vector<bool> output_data_vector = checkLogicalAndKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-TEST_F(LogicalAndTest, MismatchInputType_NEG)
+TEST_F(LogicalAndTest, Input_type_mismatch_NEG)
{
- Tensor input1_tensor =
- makeInputTensor<DataType::S32>({1, 1, 1, 4}, {1, 0, 0, 1}, _memory_manager.get());
- Tensor input2_tensor =
- makeInputTensor<DataType::BOOL>({1, 1, 1, 1}, {false}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S32);
-
- LogicalAnd kernel(&input1_tensor, &input2_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(LogicalAndTest, InputTypeInvalid_NEG)
-{
- Tensor input1_tensor =
- makeInputTensor<DataType::S32>({1, 1, 1, 4}, {1, 0, 0, 1}, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::S32>({1, 1, 1, 1}, {0}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- LogicalAnd kernel(&input1_tensor, &input2_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::NegTestDataInputTypeMismatchLogicalAndKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/LogicalNot.cpp b/onert-micro/luci-interpreter/src/kernels/LogicalNot.cpp
index 22dc0d231..4ba4499e9 100644
--- a/onert-micro/luci-interpreter/src/kernels/LogicalNot.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/LogicalNot.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/LogicalNot.h b/onert-micro/luci-interpreter/src/kernels/LogicalNot.h
deleted file mode 100644
index 6c4cfc14d..000000000
--- a/onert-micro/luci-interpreter/src/kernels/LogicalNot.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_LOGICALNOT_H
-#define LUCI_INTERPRETER_KERNELS_LOGICALNOT_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class LogicalNot : public Kernel
-{
-public:
- LogicalNot(const Tensor *input, Tensor *output);
-
- const Tensor *input() const { return _inputs[0]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-
-private:
- inline void evalLogicalNot() const;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_LOGICALNOT_H
diff --git a/onert-micro/luci-interpreter/src/kernels/LogicalOr.cpp b/onert-micro/luci-interpreter/src/kernels/LogicalOr.cpp
index ecb8ee49b..207c73964 100644
--- a/onert-micro/luci-interpreter/src/kernels/LogicalOr.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/LogicalOr.cpp
@@ -14,37 +14,58 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-#include "kernels/LogicalOr.h"
-
+#include "Builders.h"
#include "kernels/Utils.h"
-#include "kernels/BinaryOpCommon.h"
+#include "TISOKernel.h"
+
+#include "PALLogicalCommon.h"
namespace luci_interpreter
{
-namespace kernels
-{
-LogicalOr::LogicalOr(const Tensor *input1, const Tensor *input2, Tensor *output)
- : Kernel({input1, input2}, {output})
+namespace
{
-}
+bool LogicalOr(bool x, bool y) { return x || y; }
+} // namespace
-void LogicalOr::configure()
+void configure_kernel_CircleLogicalOr(const circle::Operator *cur_op,
+ BaseRuntimeGraph *runtime_graph)
{
- LUCI_INTERPRETER_CHECK(input1()->element_type() == input2()->element_type());
- LUCI_INTERPRETER_CHECK(input1()->element_type() == DataType::BOOL);
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(calculateShapeForBroadcast(input1()->shape(), input2()->shape()));
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
+
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+ Tensor::element_type(kernel.input2()));
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) == DataType::BOOL);
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.output()) == DataType::BOOL);
+
+ // TODO support broadcast
+ LUCI_INTERPRETER_CHECK(Tensor::num_elements(kernel.input1()) ==
+ Tensor::num_elements(kernel.input2()));
+ LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.input1()) == Tensor::num_dims(kernel.input2()));
}
-void LogicalOr::execute() const
+// TODO: add inplace
+// TODO: reduce code duplication with LogicalAnd
+void execute_kernel_CircleLogicalOr(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- BinaryOpBroadcastSlow(getTensorShape(input1()), getTensorData<bool>(input1()),
- getTensorShape(input2()), getTensorData<bool>(input2()),
- getTensorShape(output()), getTensorData<bool>(output()),
- [](bool x, bool y) { return x || y; });
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
+
+ auto x_data = kernels::getTensorData<bool>(runtime_graph->getDataByTensor(kernel.input1()));
+ if (x_data == nullptr)
+ x_data = kernels::getTensorData<bool>(runtime_graph->getConstDataByTensor(kernel.input1()));
+
+ assert(x_data != nullptr);
+
+ auto y_data = kernels::getTensorData<bool>(runtime_graph->getDataByTensor(kernel.input2()));
+ if (y_data == nullptr)
+ y_data = kernels::getTensorData<bool>(runtime_graph->getConstDataByTensor(kernel.input2()));
+
+ assert(y_data != nullptr);
+
+ auto output_data = kernels::getTensorData<bool>(runtime_graph->getDataByTensor(kernel.output()));
+
+ const int64_t flat_size = kernels::getTensorShape(kernel.input1()).flatSize();
+ luci_interpreter_pal::LogicalCommon(flat_size, x_data, y_data, output_data, LogicalOr);
}
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/LogicalOr.h b/onert-micro/luci-interpreter/src/kernels/LogicalOr.h
deleted file mode 100644
index 88606483f..000000000
--- a/onert-micro/luci-interpreter/src/kernels/LogicalOr.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_LOGICALOR_H
-#define LUCI_INTERPRETER_KERNELS_LOGICALOR_H
-
-#include "core/Kernel.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class LogicalOr : public Kernel
-{
-public:
- LogicalOr(const Tensor *input1, const Tensor *input2, Tensor *output);
-
- const Tensor *input1() const { return _inputs[0]; }
- const Tensor *input2() const { return _inputs[1]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_LOGICALOR_H
diff --git a/onert-micro/luci-interpreter/src/kernels/LogicalOr.test.cpp b/onert-micro/luci-interpreter/src/kernels/LogicalOr.test.cpp
index d65a69a5e..baa338d5a 100644
--- a/onert-micro/luci-interpreter/src/kernels/LogicalOr.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/LogicalOr.test.cpp
@@ -15,14 +15,14 @@
* limitations under the License.
*/
-#include "kernels/LogicalOr.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/logical_or/BoolLogicalOrKernel.h"
+#include "luci_interpreter/test_models/logical_or/NegLogicalOrKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
@@ -30,75 +30,66 @@ using namespace testing;
class LogicalOrTest : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-TEST_F(LogicalOrTest, Basic)
-{
- Tensor input1_tensor = makeInputTensor<DataType::BOOL>({1, 1, 1, 4}, {true, false, false, true},
- _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::BOOL>({1, 1, 1, 4}, {true, false, true, false},
- _memory_manager.get());
-
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- LogicalOr kernel(&input1_tensor, &input2_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<bool>(output_tensor),
- ::testing::ElementsAre(true, false, true, true));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAre(1, 1, 1, 4));
-}
-
-TEST_F(LogicalOrTest, Broadcast)
+template <typename T>
+std::vector<T> checkLogicalOrKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- Tensor input1_tensor = makeInputTensor<DataType::BOOL>({1, 1, 1, 4}, {true, false, false, true},
- _memory_manager.get());
- Tensor input2_tensor =
- makeInputTensor<DataType::BOOL>({1, 1, 1, 1}, {false}, _memory_manager.get());
-
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- LogicalOr kernel(&input1_tensor, &input2_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<bool>(output_tensor),
- ::testing::ElementsAre(true, false, false, true));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAre(1, 1, 1, 4));
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
+
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 2);
+
+ // set left input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
+
+ // set right input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(1));
+ std::copy(test_data_base->get_input_data_by_index(1).begin(),
+ test_data_base->get_input_data_by_index(1).end(), input_tensor_data);
+ }
+
+ runtime_module.execute();
+
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
+
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST_F(LogicalOrTest, MismatchInputType_NEG)
+TEST_F(LogicalOrTest, Bool_P)
{
- Tensor input1_tensor =
- makeInputTensor<DataType::S32>({1, 1, 1, 4}, {1, 0, 0, 1}, _memory_manager.get());
- Tensor input2_tensor =
- makeInputTensor<DataType::BOOL>({1, 1, 1, 1}, {false}, _memory_manager.get());
-
- Tensor output_tensor = makeOutputTensor(DataType::S32);
-
- LogicalOr kernel(&input1_tensor, &input2_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::TestDataBoolLogicalOr test_data_kernel;
+ std::vector<bool> output_data_vector = checkLogicalOrKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-TEST_F(LogicalOrTest, InputTypeInvalid_NEG)
+TEST_F(LogicalOrTest, Input_type_mismatch_NEG)
{
- Tensor input1_tensor =
- makeInputTensor<DataType::S32>({1, 1, 1, 4}, {1, 0, 0, 1}, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::S32>({1, 1, 1, 1}, {0}, _memory_manager.get());
-
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- LogicalOr kernel(&input1_tensor, &input2_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::NegTestDataInputTypeMismatchLogicalOrKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Logistic.cpp b/onert-micro/luci-interpreter/src/kernels/Logistic.cpp
index 4e8cba82b..4dbc15356 100644
--- a/onert-micro/luci-interpreter/src/kernels/Logistic.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Logistic.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,59 +16,10 @@
#include "Builders.h"
#include "kernels/Utils.h"
-
-#include <tensorflow/lite/kernels/internal/reference/logistic.h>
+#include "PALLogistic.h"
namespace luci_interpreter
{
-namespace
-{
-
-#ifndef DIS_FLOAT
-void evalFloat(const circle::Tensor *input, const circle::Tensor *output, bool is_inplace,
- BaseRuntimeGraph *runtime_graph)
-{
- const float *input_data = reinterpret_cast<const float *>(runtime_graph->getDataByTensor(input));
- float *output_data = reinterpret_cast<float *>(runtime_graph->getDataByTensor(output));
-
- if (is_inplace)
- {
- output_data = const_cast<float *>(input_data);
- }
-
- assert(input_data != nullptr);
- assert(output_data != nullptr);
-
- tflite::reference_ops::Logistic(kernels::getTensorShape(input), input_data,
- kernels::getTensorShape(output), output_data);
- if (is_inplace)
- {
- runtime_graph->makeInplaceOperation(input, output);
- }
-}
-#endif // DIS_FLOAT
-
-#ifndef DIS_QUANT
-void evalQuantized(const circle::Tensor *input, const circle::Tensor *output, bool is_inplace,
- BaseRuntimeGraph *runtime_graph)
-{
- const int8_t *input_data =
- reinterpret_cast<const int8_t *>(runtime_graph->getDataByTensor(input));
- int8_t *output_data = reinterpret_cast<int8_t *>(runtime_graph->getDataByTensor(output));
- if (is_inplace)
- output_data = const_cast<int8_t *>(input_data);
-
- tflite::reference_ops::Logistic(kernels::getTensorShape(input), input_data, Tensor::scale(input),
- Tensor::zero_point(input), kernels::getTensorShape(output),
- output_data, Tensor::scale(output), Tensor::zero_point(output));
- if (is_inplace)
- {
- runtime_graph->makeInplaceOperation(input, output);
- }
-}
-#endif // DIS_QUANT
-
-} // namespace
void configure_kernel_CircleLogistic(const circle::Operator *cur_op,
BaseRuntimeGraph *runtime_graph)
@@ -96,8 +46,7 @@ void configure_kernel_CircleLogistic(const circle::Operator *cur_op,
#endif // DIS_QUANT
}
-void execute_kernel_CircleLogistic(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph,
- bool is_inplace)
+void execute_kernel_CircleLogistic(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
const auto input_index = cur_op->inputs()->operator[](0);
const auto output_index = cur_op->outputs()->operator[](0);
@@ -111,21 +60,45 @@ void execute_kernel_CircleLogistic(const circle::Operator *cur_op, BaseRuntimeGr
assert(input != nullptr);
assert(output != nullptr);
+ bool is_inplace = runtime_graph->is_inplace_op(cur_op);
+
+ const uint8_t *input_data = runtime_graph->getDataByTensor(input);
+ uint8_t *output_data = runtime_graph->getDataByTensor(output);
+
+ if (is_inplace)
+ {
+ output_data = const_cast<uint8_t *>(input_data);
+ }
+
+ assert(input_data != nullptr);
+ assert(output_data != nullptr);
+
+ const int flat_size = kernels::getTensorRuntimeShape(input, runtime_graph).flatSize();
+
switch (Tensor::element_type(input))
{
#ifndef DIS_FLOAT
case DataType::FLOAT32:
- evalFloat(input, output, is_inplace, runtime_graph);
+ luci_interpreter_pal::Logistic(flat_size, kernels::getTensorData<float>(input_data),
+ kernels::getTensorData<float>(output_data));
break;
#endif // DIS_FLOAT
#ifndef DIS_QUANT
case DataType::S8:
- evalQuantized(input, output, is_inplace, runtime_graph);
+ luci_interpreter_pal::Logistic(flat_size, kernels::getTensorData<int8_t>(input_data),
+ Tensor::scale(input), Tensor::zero_point(input),
+ kernels::getTensorData<int8_t>(output_data),
+ Tensor::scale(output), Tensor::zero_point(output));
break;
#endif // DIS_QUANT
default:
assert(false && "Unsupported type.");
}
+
+ if (is_inplace)
+ {
+ runtime_graph->makeInplaceOperation(input, output);
+ }
}
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Logistic.test.cpp b/onert-micro/luci-interpreter/src/kernels/Logistic.test.cpp
index 78fa9ee06..36e347038 100644
--- a/onert-micro/luci-interpreter/src/kernels/Logistic.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Logistic.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,138 +13,89 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-// TODO enable it
-#if 0
-#include "kernels/Logistic.h"
+
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/logistic/FloatLogisticKernel.h"
+#include "luci_interpreter/test_models/logistic/NegLogisticKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
using namespace testing;
+class LogisticTest : public ::testing::Test
+{
+ // Do nothing
+};
+
template <typename T>
-void Check(std::initializer_list<int32_t> input_shape, std::initializer_list<int32_t> output_shape,
- std::initializer_list<float> input_data, std::initializer_list<float> output_data)
+std::vector<T> checkLogisticKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- Tensor input_tensor =
- makeInputTensor<getElementType<T>()>(input_shape, input_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(getElementType<T>());
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- Logistic kernel(&input_tensor, &output_tensor);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
- EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
-}
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
-template <>
-void Check<uint8_t>(std::initializer_list<int32_t> input_shape,
- std::initializer_list<int32_t> output_shape,
- std::initializer_list<float> input_data,
- std::initializer_list<float> output_data)
-{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-
- std::pair<float, int32_t> input_quant_param =
- quantizationParams<uint8_t>(std::min(input_data), std::max(input_data));
- Tensor input_tensor =
- makeInputTensor<DataType::U8>(input_shape, input_quant_param.first, input_quant_param.second,
- input_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U8, 1. / 256, 0);
-
- Logistic kernel(&input_tensor, &output_tensor);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(dequantizeTensorData(output_tensor),
- FloatArrayNear(output_data, output_tensor.scale() * 2));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
-}
+ runtime_module.execute();
-template <typename T> class LogisticTest : public ::testing::Test
-{
-};
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
-using DataTypes = ::testing::Types<float, uint8_t>;
-TYPED_TEST_SUITE(LogisticTest, DataTypes);
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
+}
-TYPED_TEST(LogisticTest, Simple)
+TEST_F(LogisticTest, Float_P)
{
- Check<TypeParam>(
- {89}, {89},
- {-10.0000000000, -9.7727272727, -9.5454545455, -9.3181818182, -9.0909090909, -8.8636363636,
- -8.6363636364, -8.4090909091, -8.1818181818, -7.9545454545, -7.7272727273, -7.5000000000,
- -7.2727272727, -7.0454545455, -6.8181818182, -6.5909090909, -6.3636363636, -6.1363636364,
- -5.9090909091, -5.6818181818, -5.4545454545, -5.2272727273, -5.0000000000, -4.7727272727,
- -4.5454545455, -4.3181818182, -4.0909090909, -3.8636363636, -3.6363636364, -3.4090909091,
- -3.1818181818, -2.9545454545, -2.7272727273, -2.5000000000, -2.2727272727, -2.0454545455,
- -1.8181818182, -1.5909090909, -1.3636363636, -1.1363636364, -0.9090909091, -0.6818181818,
- -0.4545454545, -0.2272727273, 0.0000000000, 0.2272727273, 0.4545454545, 0.6818181818,
- 0.9090909091, 1.1363636364, 1.3636363636, 1.5909090909, 1.8181818182, 2.0454545455,
- 2.2727272727, 2.5000000000, 2.7272727273, 2.9545454545, 3.1818181818, 3.4090909091,
- 3.6363636364, 3.8636363636, 4.0909090909, 4.3181818182, 4.5454545455, 4.7727272727,
- 5.0000000000, 5.2272727273, 5.4545454545, 5.6818181818, 5.9090909091, 6.1363636364,
- 6.3636363636, 6.5909090909, 6.8181818182, 7.0454545455, 7.2727272727, 7.5000000000,
- 7.7272727273, 7.9545454545, 8.1818181818, 8.4090909091, 8.6363636364, 8.8636363636,
- 9.0909090909, 9.3181818182, 9.5454545455, 9.7727272727, 10.0000000000},
- {0.0000453979, 0.0000569815, 0.0000715205, 0.0000897689, 0.0001126729, 0.0001414198,
- 0.0001774998, 0.0002227827, 0.0002796147, 0.0003509396, 0.0004404502, 0.0005527786,
- 0.0006937345, 0.0008706021, 0.0010925128, 0.0013709094, 0.0017201256, 0.0021581065,
- 0.0027073042, 0.0033957870, 0.0042586071, 0.0053394826, 0.0066928509, 0.0083863576,
- 0.0105038445, 0.0131488902, 0.0164489307, 0.0205599431, 0.0256715863, 0.0320125562,
- 0.0398556989, 0.0495221198, 0.0613831074, 0.0758581800, 0.0934070047, 0.1145124805,
- 0.1396521834, 0.1692560327, 0.2036499335, 0.2429886272, 0.2871859014, 0.3358556241,
- 0.3882805886, 0.4434251301, 0.5000000000, 0.5565748699, 0.6117194114, 0.6641443759,
- 0.7128140986, 0.7570113728, 0.7963500665, 0.8307439673, 0.8603478166, 0.8854875195,
- 0.9065929953, 0.9241418200, 0.9386168926, 0.9504778802, 0.9601443011, 0.9679874438,
- 0.9743284137, 0.9794400569, 0.9835510693, 0.9868511098, 0.9894961555, 0.9916136424,
- 0.9933071491, 0.9946605174, 0.9957413929, 0.9966042130, 0.9972926958, 0.9978418935,
- 0.9982798744, 0.9986290906, 0.9989074872, 0.9991293979, 0.9993062655, 0.9994472214,
- 0.9995595498, 0.9996490604, 0.9997203853, 0.9997772173, 0.9998225002, 0.9998585802,
- 0.9998873271, 0.9999102311, 0.9999284795, 0.9999430185, 0.9999546021});
+ test_kernel::TestDataFloatLogistic test_data_kernel;
+ std::vector<float> output_data_vector = checkLogisticKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-TEST(LogisticTest, IvalidInputOutputType_NEG)
+TEST_F(LogisticTest, Input_output_type_mismatch_NEG)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-
- Shape input_shape = {1};
- std::vector<float> input_data{10};
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U8, 1. / 256, 0);
-
- Logistic kernel(&input_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::NegTestDataInputOutputTypeMismatchLogisticKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST(LogisticTest, IvalidQuantParam_NEG)
+TEST_F(LogisticTest, No_quant_params_NEG)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- Shape input_shape = {2};
- std::vector<float> input_data{-10, 10};
- std::pair<float, int32_t> input_quant_param = quantizationParams<uint8_t>(-10, 10);
- Tensor input_tensor =
- makeInputTensor<DataType::U8>(input_shape, input_quant_param.first, input_quant_param.second,
- input_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U8, 1. / 255, 0);
-
- Logistic kernel(&input_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::NegTestDataNoQuantParamsLogisticKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
+// TODO: add S8 test
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
-#endif
diff --git a/onert-micro/luci-interpreter/src/kernels/MISOKernel.h b/onert-micro/luci-interpreter/src/kernels/MISOKernel.h
new file mode 100644
index 000000000..96d20af3f
--- /dev/null
+++ b/onert-micro/luci-interpreter/src/kernels/MISOKernel.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_KERNELS_MISO_KERNEL_H
+#define LUCI_INTERPRETER_KERNELS_MISO_KERNEL_H
+
+#include "Builders.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+// Multiple input single output kernel
+class MISOKernel
+{
+public:
+ MISOKernel(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+ {
+ const auto input1_index = cur_op->inputs()->operator[](0);
+ const auto input2_index = cur_op->inputs()->operator[](1);
+ const auto input3_index = cur_op->inputs()->operator[](2);
+ const auto input4_index =
+ cur_op->inputs()->size() == 4 ? cur_op->inputs()->operator[](3) : -1; // optional
+
+ const auto output_index = cur_op->outputs()->operator[](0);
+
+ assert(input1_index != -1);
+ assert(input2_index != -1);
+ assert(input3_index != -1);
+
+ assert(output_index != -1);
+
+ _input1_tensor = runtime_graph->getCircleTensorByIndex(input1_index);
+ _input2_tensor = runtime_graph->getCircleTensorByIndex(input2_index);
+ _input3_tensor = runtime_graph->getCircleTensorByIndex(input3_index);
+ _output_tensor = runtime_graph->getCircleTensorByIndex(output_index);
+
+ // optional
+ if (input4_index != -1)
+ _input4_tensor = runtime_graph->getCircleTensorByIndex(input4_index);
+ else
+ _input4_tensor = nullptr;
+
+ assert(_input1_tensor != nullptr);
+ assert(_input2_tensor != nullptr);
+ assert(_input3_tensor != nullptr);
+ assert(_output_tensor != nullptr);
+ }
+
+ const circle::Tensor *input1() const { return _input1_tensor; }
+ const circle::Tensor *input2() const { return _input2_tensor; }
+ const circle::Tensor *input3() const { return _input3_tensor; }
+
+ const circle::Tensor *input4() const
+ {
+ assert(_input4_tensor != nullptr);
+ return _input4_tensor;
+ }
+
+ const circle::Tensor *output() const { return _output_tensor; }
+
+private:
+ const circle::Tensor *_input1_tensor;
+ const circle::Tensor *_input2_tensor;
+ const circle::Tensor *_input3_tensor;
+ const circle::Tensor *_input4_tensor; // optional
+ const circle::Tensor *_output_tensor;
+};
+
+} // namespace kernels
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_KERNELS_MISO_KERNEL_H
diff --git a/onert-micro/luci-interpreter/src/kernels/MaxPool2D.cpp b/onert-micro/luci-interpreter/src/kernels/MaxPool2D.cpp
index f6b521db3..d85e8a980 100644
--- a/onert-micro/luci-interpreter/src/kernels/MaxPool2D.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/MaxPool2D.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,143 +17,10 @@
#include "Builders.h"
#include "kernels/Utils.h"
-
-#include <tensorflow/lite/kernels/internal/reference/integer_ops/pooling.h>
-#include <tensorflow/lite/kernels/internal/reference/pooling.h>
+#include "PALMaxPool2D.h"
namespace luci_interpreter
{
-
-namespace
-{
-
-#ifndef DIS_FLOAT
-
-void evalFloat(const circle::Tensor *input, const circle::Tensor *output,
- const circle::Pool2DOptions *options, BaseRuntimeGraph *runtime_graph)
-{
- const int32_t input_height = Tensor::dim(input, 1);
- const int32_t input_width = Tensor::dim(input, 2);
-
- const int32_t output_height = kernels::computeOutputSize(
- luci_padding(options->padding()), input_height, options->filter_height(), options->stride_h());
- const int32_t output_width = kernels::computeOutputSize(
- luci_padding(options->padding()), input_width, options->filter_width(), options->stride_w());
-
- const auto padding_height = kernels::computePadding(options->stride_h(), 1, input_height,
- options->filter_height(), output_height);
- const auto padding_width = kernels::computePadding(options->stride_w(), 1, input_width,
- options->filter_width(), output_width);
-
- const auto *input_data = runtime_graph->getDataByTensor(input);
- auto *output_data = runtime_graph->getDataByTensor(output);
-
- float activation_min{};
- float activation_max{};
- kernels::calculateActivationRange(luci_actfunc(options->fused_activation_function()),
- &activation_min, &activation_max);
- tflite::PoolParams params{};
- params.padding_values.height = padding_height;
- params.padding_values.width = padding_width;
- params.stride_height = options->stride_h();
- params.stride_width = options->stride_w();
- params.filter_height = options->filter_height();
- params.filter_width = options->filter_width();
- params.float_activation_min = activation_min;
- params.float_activation_max = activation_max;
-
- tflite::reference_ops::MaxPool(
- params, kernels::getTensorShape(input), kernels::getTensorData<float>(input_data),
- kernels::getTensorShape(output), kernels::getTensorData<float>(output_data));
-}
-
-#endif // DIS_FLOAT
-
-#ifndef DIS_QUANT
-void evalQuantized(const circle::Tensor *input, const circle::Tensor *output,
- const circle::Pool2DOptions *options, BaseRuntimeGraph *runtime_graph)
-{
- int32_t activation_min{};
- int32_t activation_max{};
- kernels::calculateActivationRangeQuantized(luci_actfunc(options->fused_activation_function()),
- output, &activation_min, &activation_max);
-
- // Compute padding
- const int32_t input_height = Tensor::dim(input, 1);
- const int32_t input_width = Tensor::dim(input, 2);
-
- const int32_t output_height = kernels::computeOutputSize(
- luci_padding(options->padding()), input_height, options->filter_height(), options->stride_h());
- const int32_t output_width = kernels::computeOutputSize(
- luci_padding(options->padding()), input_width, options->filter_width(), options->stride_w());
-
- const auto padding_height = kernels::computePadding(options->stride_h(), 1, input_height,
- options->filter_height(), output_height);
- const auto padding_width = kernels::computePadding(options->stride_w(), 1, input_width,
- options->filter_width(), output_width);
-
- tflite::PoolParams params{};
- params.padding_values.height = padding_height;
- params.padding_values.width = padding_width;
- params.stride_height = options->stride_h();
- params.stride_width = options->stride_w();
- params.filter_height = options->filter_height();
- params.filter_width = options->filter_width();
- params.quantized_activation_min = activation_min;
- params.quantized_activation_max = activation_max;
-
- const auto *input_data = runtime_graph->getDataByTensor(input);
- auto *output_data = runtime_graph->getDataByTensor(output);
-
- tflite::reference_ops::MaxPool(
- params, kernels::getTensorShape(input), kernels::getTensorData<uint8_t>(input_data),
- kernels::getTensorShape(output), kernels::getTensorData<uint8_t>(output_data));
-}
-
-void evalSInt16(const circle::Tensor *input, const circle::Tensor *output,
- const circle::Pool2DOptions *options, BaseRuntimeGraph *runtime_graph)
-{
- int32_t activation_min{};
- int32_t activation_max{};
- kernels::calculateActivationRangeQuantized(luci_actfunc(options->fused_activation_function()),
- output, &activation_min, &activation_max);
-
- // Compute padding
- const int32_t input_height = Tensor::dim(input, 1);
- const int32_t input_width = Tensor::dim(input, 2);
-
- const int32_t output_height = kernels::computeOutputSize(
- luci_padding(options->padding()), input_height, options->filter_height(), options->stride_h());
- const int32_t output_width = kernels::computeOutputSize(
- luci_padding(options->padding()), input_width, options->filter_width(), options->stride_w());
-
- const auto padding_height = kernels::computePadding(options->stride_h(), 1, input_height,
- options->filter_height(), output_height);
- const auto padding_width = kernels::computePadding(options->stride_w(), 1, input_width,
- options->filter_width(), output_width);
-
- tflite::PoolParams params{};
- params.padding_values.height = padding_height;
- params.padding_values.width = padding_width;
- params.stride_height = options->stride_h();
- params.stride_width = options->stride_w();
- params.filter_height = options->filter_height();
- params.filter_width = options->filter_width();
- params.quantized_activation_min = activation_min;
- params.quantized_activation_max = activation_max;
-
- const auto *input_data = runtime_graph->getDataByTensor(input);
- auto *output_data = runtime_graph->getDataByTensor(output);
-
- tflite::reference_integer_ops::MaxPool(
- params, kernels::getTensorShape(input), kernels::getTensorData<int16_t>(input_data),
- kernels::getTensorShape(output), kernels::getTensorData<int16_t>(output_data));
-}
-
-#endif // DIS_QUANT
-
-} // namespace
-
void configure_kernel_CircleMaxPool2D(const circle::Operator *cur_op,
BaseRuntimeGraph *runtime_graph)
{
@@ -184,8 +50,7 @@ void configure_kernel_CircleMaxPool2D(const circle::Operator *cur_op,
#endif // DIS_QUANT
}
-void execute_kernel_CircleMaxPool2D(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph,
- bool)
+void execute_kernel_CircleMaxPool2D(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
const auto input_index = cur_op->inputs()->operator[](0);
const auto output_index = cur_op->outputs()->operator[](0);
@@ -198,19 +63,55 @@ void execute_kernel_CircleMaxPool2D(const circle::Operator *cur_op, BaseRuntimeG
const auto *options = cur_op->builtin_options_as_Pool2DOptions();
+ const int32_t input_height = Tensor::dim(input, 1);
+ const int32_t input_width = Tensor::dim(input, 2);
+
+ const int32_t output_height = kernels::computeOutputSize(
+ luci_padding(options->padding()), input_height, options->filter_height(), options->stride_h());
+ const int32_t output_width = kernels::computeOutputSize(
+ luci_padding(options->padding()), input_width, options->filter_width(), options->stride_w());
+
+ const auto padding_height = kernels::computePadding(options->stride_h(), 1, input_height,
+ options->filter_height(), output_height);
+ const auto padding_width = kernels::computePadding(options->stride_w(), 1, input_width,
+ options->filter_width(), output_width);
+
+ const auto *input_data = runtime_graph->getDataByTensor(input);
+ auto *output_data = runtime_graph->getDataByTensor(output);
+
+ float activation_min{};
+ float activation_max{};
+ kernels::calculateActivationRange(luci_actfunc(options->fused_activation_function()),
+ &activation_min, &activation_max);
+ luci_interpreter_pal::PoolParams params{};
+ params.padding_values.height = padding_height;
+ params.padding_values.width = padding_width;
+ params.stride_height = options->stride_h();
+ params.stride_width = options->stride_w();
+ params.filter_height = options->filter_height();
+ params.filter_width = options->filter_width();
+ params.float_activation_min = activation_min;
+ params.float_activation_max = activation_max;
+
switch (Tensor::element_type(input))
{
#ifndef DIS_FLOAT
case DataType::FLOAT32:
- evalFloat(input, output, options, runtime_graph);
+ luci_interpreter_pal::MaxPool(
+ params, kernels::getTensorShape(input), kernels::getTensorData<float>(input_data),
+ kernels::getTensorShape(output), kernels::getTensorData<float>(output_data));
break;
#endif // DIS_FLOAT
#ifndef DIS_QUANT
case DataType::U8:
- evalQuantized(input, output, options, runtime_graph);
+ luci_interpreter_pal::MaxPool(
+ params, kernels::getTensorShape(input), kernels::getTensorData<uint8_t>(input_data),
+ kernels::getTensorShape(output), kernels::getTensorData<uint8_t>(output_data));
break;
case DataType::S16:
- evalSInt16(input, output, options, runtime_graph);
+ luci_interpreter_pal::MaxPool(
+ params, kernels::getTensorShape(input), kernels::getTensorData<int16_t>(input_data),
+ kernels::getTensorShape(output), kernels::getTensorData<int16_t>(output_data));
break;
#endif // DIS_QUANT
default:
diff --git a/onert-micro/luci-interpreter/src/kernels/MaxPool2D.test.cpp b/onert-micro/luci-interpreter/src/kernels/MaxPool2D.test.cpp
index 9e3cbac5e..d7af7d7c5 100644
--- a/onert-micro/luci-interpreter/src/kernels/MaxPool2D.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/MaxPool2D.test.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,16 +14,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-// TODO enable it
-#if 0
-#include "kernels/MaxPool2D.h"
+
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/maxpool2d/FloatMaxPool2DKernel.h"
+#include "luci_interpreter/test_models/maxpool2d/NegMaxPool2DKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
@@ -31,112 +30,88 @@ using namespace testing;
class MaxPool2DTest : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-TEST_F(MaxPool2DTest, Float)
+template <typename T>
+std::vector<T> checkMaxPool2DKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- Shape input_shape{1, 3, 5, 1};
- std::vector<float> input_data{
- 1, -1, 0, -2, 2, //
- -7, -6, -5, -4, -3, //
- 5, 4, 3, 6, 7, //
- };
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- Pool2DParams params{};
- params.padding = Padding::VALID;
- params.filter_height = 2;
- params.filter_width = 3;
- params.stride_height = 1;
- params.stride_width = 2;
- params.activation = Activation::RELU6;
-
- MaxPool2D kernel(&input_tensor, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- std::vector<float> ref_output_data{
- 1, 2, //
- 5, 6, //
- };
- std::initializer_list<int32_t> ref_output_shape{1, 2, 2, 1};
- EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
+
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
+
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
+
+ runtime_module.execute();
+
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
+
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
+}
+
+TEST_F(MaxPool2DTest, Float_P)
+{
+ test_kernel::TestDataFloatMaxPool2D test_data_kernel;
+ std::vector<float> output_data_vector = checkMaxPool2DKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+ test_data_kernel.get_output_data_by_index(0), 0.01f));
}
-TEST_F(MaxPool2DTest, Uint8)
+TEST_F(MaxPool2DTest, InputOutputTypeMismatch_NEG)
{
- std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(-15.9375, 15.9375);
- std::vector<float> input_data{
- 0, -6, 12, 4, //
- -3, -2, 10, 7, //
- };
- Tensor input_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, quant_param.first, quant_param.second, input_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.second);
-
- Pool2DParams params{};
- params.padding = Padding::VALID;
- params.filter_height = 2;
- params.filter_width = 2;
- params.stride_height = 2;
- params.stride_width = 2;
- params.activation = Activation::RELU6;
-
- MaxPool2D kernel(&input_tensor, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- std::vector<float> ref_output_data{0.0, 6.0};
- std::initializer_list<int32_t> ref_output_shape{1, 1, 2, 1};
- EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+ test_kernel::NegTestDataInputOutputTypeMismatchMaxPool2DKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST_F(MaxPool2DTest, SInt16)
+TEST_F(MaxPool2DTest, Invalid_input_shape_NEG)
{
- Shape input_shape{1, 3, 5, 1};
- std::vector<int32_t> ref_output_shape{1, 2, 2, 1};
- std::vector<float> input_data{
- 1, -1, 0, -2, 2, //
- -7, -6, -5, -4, -3, //
- 5, 4, 3, 6, 7, //
- };
- std::vector<float> ref_output_data{
- 1, 2, //
- 5, 6, //
- };
-
- Tensor input_tensor =
- makeInputTensor<DataType::S16>(input_shape, 0.2, 0, input_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S16, 0.2, 0);
-
- Pool2DParams params{};
- params.padding = Padding::VALID;
- params.filter_height = 2;
- params.filter_width = 3;
- params.stride_height = 1;
- params.stride_width = 2;
- params.activation = Activation::RELU6;
-
- MaxPool2D kernel(&input_tensor, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
- EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
+ test_kernel::NegTestDataInvalidInputShapeMaxPool2DKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
+TEST_F(MaxPool2DTest, No_quant_params_NEG)
+{
+ test_kernel::NegTestDataNoQuantParamsMaxPool2DKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
+}
+
+// TODO: add S16 test
+
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
-#ednif
diff --git a/onert-micro/luci-interpreter/src/kernels/Maximum.h b/onert-micro/luci-interpreter/src/kernels/Maximum.h
index 275d5d36e..3c99e69c7 100644
--- a/onert-micro/luci-interpreter/src/kernels/Maximum.h
+++ b/onert-micro/luci-interpreter/src/kernels/Maximum.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Mean.h b/onert-micro/luci-interpreter/src/kernels/Mean.h
index 9739f5429..ed07ae561 100644
--- a/onert-micro/luci-interpreter/src/kernels/Mean.h
+++ b/onert-micro/luci-interpreter/src/kernels/Mean.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Minimum.h b/onert-micro/luci-interpreter/src/kernels/Minimum.h
index ad1c8fcb7..5ff4035b4 100644
--- a/onert-micro/luci-interpreter/src/kernels/Minimum.h
+++ b/onert-micro/luci-interpreter/src/kernels/Minimum.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/MirrorPad.h b/onert-micro/luci-interpreter/src/kernels/MirrorPad.h
index 5919e3d46..d3e6e858a 100644
--- a/onert-micro/luci-interpreter/src/kernels/MirrorPad.h
+++ b/onert-micro/luci-interpreter/src/kernels/MirrorPad.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/MirrorPad.test.cpp b/onert-micro/luci-interpreter/src/kernels/MirrorPad.test.cpp
index f6f938cdf..740d8cb22 100644
--- a/onert-micro/luci-interpreter/src/kernels/MirrorPad.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/MirrorPad.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Mul.cpp b/onert-micro/luci-interpreter/src/kernels/Mul.cpp
index bac9fe393..75f9b9047 100644
--- a/onert-micro/luci-interpreter/src/kernels/Mul.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Mul.cpp
@@ -15,134 +15,142 @@
* limitations under the License.
*/
-#include "kernels/Mul.h"
+#include "Builders.h"
+#include "kernels/Utils.h"
#include "kernels/BinaryOpCommon.h"
-#include "kernels/Utils.h"
#include "PALMul.h"
-#include <tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h>
-
namespace luci_interpreter
{
-namespace kernels
-{
-
-Mul::Mul(const Tensor *input1, const Tensor *input2, Tensor *output, const MulParams &params)
- : KernelWithParams<MulParams>({input1, input2}, {output}, params)
-{
-}
-void Mul::configure()
+void configure_kernel_CircleMul(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- LUCI_INTERPRETER_CHECK(input1()->element_type() == input2()->element_type());
- LUCI_INTERPRETER_CHECK(output()->element_type() == input1()->element_type());
- if (input1()->element_type() == DataType::S16)
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
+
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+ Tensor::element_type(kernel.input2()));
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+ Tensor::element_type(kernel.input2()));
+#ifndef DIS_QUANT
+ if (Tensor::element_type(kernel.input1()) == DataType::S16)
{
- LUCI_INTERPRETER_CHECK(input1()->zero_points().size() == 1 &&
- input2()->zero_points().size() == 1)
- LUCI_INTERPRETER_CHECK(input1()->zero_point() == 0 && input2()->zero_point() == 0 &&
- output()->zero_point() == 0);
+ LUCI_INTERPRETER_CHECK(Tensor::zero_points(kernel.input1()).size() == 1 &&
+ Tensor::zero_points(kernel.input2()).size() == 1);
+ LUCI_INTERPRETER_CHECK(Tensor::zero_point(kernel.input1()) == 0 &&
+ Tensor::zero_point(kernel.input2()) == 0 &&
+ Tensor::zero_point(kernel.output()) == 0);
}
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(calculateShapeForBroadcast(input1()->shape(), input2()->shape()));
+#endif // DIS_QUANT
}
-void Mul::execute() const
+void execute_kernel_CircleMul(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- switch (input1()->element_type())
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
+
+ const auto *options = cur_op->builtin_options_as_MulOptions();
+
+ luci_interpreter::RuntimeShape input_shape1 =
+ kernels::getTensorRuntimeShape(kernel.input1(), runtime_graph);
+ luci_interpreter::RuntimeShape input_shape2 =
+ kernels::getTensorRuntimeShape(kernel.input2(), runtime_graph);
+
+ bool is_inplace = runtime_graph->is_inplace_op(cur_op);
+
+ switch (Tensor::element_type(kernel.input1()))
{
+#ifndef DIS_FLOAT
case DataType::FLOAT32:
- evalFloat();
- break;
+ {
+ auto tiso_func = luci_interpreter_pal::Mul<float>;
+ auto broadcast_tiso_func = luci_interpreter_pal::BroadcastMul4DSlow<float>;
+ if (is_inplace)
+ {
+ kernels::evalTISOInplaceKernel<float>(tiso_func, broadcast_tiso_func, &kernel, options,
+ std::move(input_shape1), std::move(input_shape2));
+ }
+ else
+ {
+ kernels::TISOData kernel_data = kernel.readData();
+ kernels::evalTISOKernel<float>(tiso_func, broadcast_tiso_func, &kernel, &kernel_data,
+ options, std::move(input_shape1), std::move(input_shape2));
+ }
+ }
+ break;
+#endif // DIS_FLOAT
case DataType::S64:
- evalInteger<int64_t>();
- break;
+ {
+ auto tiso_func = luci_interpreter_pal::Mul<int64_t>;
+ auto broadcast_tiso_func = luci_interpreter_pal::BroadcastMul4DSlow<int64_t>;
+ if (is_inplace)
+ {
+ kernels::evalTISOInplaceKernel<int64_t>(tiso_func, broadcast_tiso_func, &kernel, options,
+ std::move(input_shape1), std::move(input_shape2));
+ }
+ else
+ {
+ kernels::TISOData kernel_data = kernel.readData();
+ kernels::evalTISOKernel<int64_t>(tiso_func, broadcast_tiso_func, &kernel, &kernel_data,
+ options, std::move(input_shape1), std::move(input_shape2));
+ }
+ }
+ break;
case DataType::S32:
- evalInteger<int32_t>();
- break;
- case DataType::S16:
- evalQuantizedS16();
- break;
+ {
+ auto tiso_func = luci_interpreter_pal::Mul<int32_t>;
+ auto broadcast_tiso_func = luci_interpreter_pal::BroadcastMul4DSlow<int32_t>;
+ if (is_inplace)
+ {
+ kernels::evalTISOInplaceKernel<int32_t>(tiso_func, broadcast_tiso_func, &kernel, options,
+ std::move(input_shape1), std::move(input_shape2));
+ }
+ else
+ {
+ kernels::TISOData kernel_data = kernel.readData();
+ kernels::evalTISOKernel<int32_t>(tiso_func, broadcast_tiso_func, &kernel, &kernel_data,
+ options, std::move(input_shape1), std::move(input_shape2));
+ }
+ }
+ break;
+#if 0
+#ifndef DIS_QUANT
+ // TODO: check quantize Mul
+ case DataType::U8:
+ {
+ auto tiso_func = [](const luci_interpreter_pal::ArithmeticParams &params,
+ const luci_interpreter::RuntimeShape &input1_shape, const uint8_t *input1_data,
+ const luci_interpreter::RuntimeShape &input2_shape, const uint8_t *input2_data,
+ const luci_interpreter::RuntimeShape &output_shape, uint8_t *output_data) {
+ luci_interpreter_pal::Mul(params, input1_shape, input1_data, input2_shape, input2_data,
+ output_shape, output_data);
+ };
+ auto broadcast_tiso_func =
+ [](const luci_interpreter_pal::ArithmeticParams &params, const luci_interpreter::RuntimeShape &input1_shape,
+ const uint8_t *input1_data, const luci_interpreter::RuntimeShape &input2_shape,
+ const uint8_t *input2_data, const luci_interpreter::RuntimeShape &output_shape,
+ uint8_t *output_data) {
+ luci_interpreter_pal::BroadcastMul4DSlow(params, input1_shape, input1_data, input2_shape,
+ input2_data, output_shape, output_data);
+ };
+ if (is_inplace)
+ {
+ kernels::evalTISOInplaceQuantizedKernel<uint8_t>(tiso_func, broadcast_tiso_func, &kernel,
+ options);
+ }
+ else
+ {
+ kernels::TISOData kernel_data = kernel.readData();
+ kernels::evalTISOQuantizedKernel<uint8_t>(tiso_func, broadcast_tiso_func, &kernel,
+ &kernel_data, options);
+ }
+ }
+ break;
+#endif // DIS_QUANT
+#endif // 0
default:
assert(false && "Unsupported type.");
}
}
-void Mul::evalFloat() const
-{
- tflite::ArithmeticParams params{};
- fillArithmeticActivationRange<float>(params, _params.activation);
-
- const bool need_broadcast = tflite::reference_ops::ProcessBroadcastShapes(
- getTensorShape(input1()), getTensorShape(input2()), &params);
-
- if (need_broadcast)
- {
- luci_interpreter_pal::BroadcastMul4DSlow(
- params, getTensorShape(input1()), getTensorData<float>(input1()), getTensorShape(input2()),
- getTensorData<float>(input2()), getTensorShape(output()), getTensorData<float>(output()));
- }
- else
- {
- luci_interpreter_pal::Mul(params, getTensorShape(input1()), getTensorData<float>(input1()),
- getTensorShape(input2()), getTensorData<float>(input2()),
- getTensorShape(output()), getTensorData<float>(output()));
- }
-}
-
-template <typename T> void Mul::evalInteger() const
-{
- tflite::ArithmeticParams params{};
- fillArithmeticActivationRange<T>(params, _params.activation);
-
- const bool need_broadcast = tflite::reference_ops::ProcessBroadcastShapes(
- getTensorShape(input1()), getTensorShape(input2()), &params);
-
- if (need_broadcast)
- {
- luci_interpreter_pal::BroadcastMul4DSlow(
- params, getTensorShape(input1()), getTensorData<T>(input1()), getTensorShape(input2()),
- getTensorData<T>(input2()), getTensorShape(output()), getTensorData<T>(output()));
- }
- else
- {
- luci_interpreter_pal::Mul(params, getTensorShape(input1()), getTensorData<T>(input1()),
- getTensorShape(input2()), getTensorData<T>(input2()),
- getTensorShape(output()), getTensorData<T>(output()));
- }
-}
-
-void Mul::evalQuantizedS16() const
-{
- const auto input1_scale = static_cast<double>(input1()->scale());
- const auto input2_scale = static_cast<double>(input2()->scale());
- const auto output_scale = static_cast<double>(output()->scale());
-
- const double real_multiplier = input1_scale * input2_scale / output_scale;
-
- int32_t output_multiplier;
- int output_shift;
- quantizeMultiplier(real_multiplier, &output_multiplier, &output_shift);
-
- int32_t activation_min{};
- int32_t activation_max{};
- calculateActivationRangeQuantized(_params.activation, output(), &activation_min, &activation_max);
-
- auto fn = [output_multiplier, output_shift, activation_min, activation_max](int16_t input1_val,
- int16_t input2_val) {
- int32_t output = static_cast<int32_t>(input1_val) * static_cast<int32_t>(input2_val);
- output = tflite::MultiplyByQuantizedMultiplier(output, output_multiplier, output_shift);
- output = std::max(output, activation_min);
- output = std::min(output, activation_max);
- return static_cast<int16_t>(output);
- };
-
- BinaryOpBroadcastSlow(getTensorShape(input1()), getTensorData<int16_t>(input1()),
- getTensorShape(input2()), getTensorData<int16_t>(input2()),
- getTensorShape(output()), getTensorData<int16_t>(output()), fn);
-}
-
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Mul.h b/onert-micro/luci-interpreter/src/kernels/Mul.h
deleted file mode 100644
index 6945abde0..000000000
--- a/onert-micro/luci-interpreter/src/kernels/Mul.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_MUL_H
-#define LUCI_INTERPRETER_KERNELS_MUL_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-#include <cstdint>
-#include <vector>
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Mul : public KernelWithParams<MulParams>
-{
-public:
- Mul(const Tensor *input1, const Tensor *input2, Tensor *output, const MulParams &params);
-
- const Tensor *input1() const { return _inputs[0]; }
- const Tensor *input2() const { return _inputs[1]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-
-private:
- void evalFloat() const;
- template <typename T> void evalInteger() const;
- void evalQuantizedS16() const;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_MUL_H
diff --git a/onert-micro/luci-interpreter/src/kernels/Mul.test.cpp b/onert-micro/luci-interpreter/src/kernels/Mul.test.cpp
index fc0e60614..391c783a1 100644
--- a/onert-micro/luci-interpreter/src/kernels/Mul.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Mul.test.cpp
@@ -15,14 +15,15 @@
* limitations under the License.
*/
-#include "kernels/Mul.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/mul/FloatMulKernel.h"
+#include "luci_interpreter/test_models/mul/IntMulKernel.h"
+#include "luci_interpreter/test_models/mul/NegMulKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
@@ -30,263 +31,125 @@ using namespace testing;
class MulTest : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-TEST_F(MulTest, Float)
+template <typename T> std::vector<T> checkMulKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- Shape base_shape = {2, 3, 1, 2};
- std::vector<Shape> test_shapes{{1, 1, 3, 2}, {1, 3, 1, 2}, {2, 1, 3, 1}, {2, 3, 1, 1}};
- std::vector<std::vector<float>> test_outputs = {
- {0.00f, 0.69f, 0.12f, 1.15f, 0.00f, 2.07f, 0.18f, 0.15f, 0.00f, 0.25f, 0.90f, 0.45f,
- 0.16f, 0.00f, 0.00f, 0.00f, 0.80f, 0.00f, 0.24f, 0.84f, 0.00f, 1.40f, 1.20f, 2.52f,
- 0.00f, 0.00f, 0.64f, 0.00f, 0.00f, 0.00f, 0.14f, 0.00f, 0.00f, 0.00f, 0.70f, 0.00f},
- {0.00f, 0.69f, 0.00f, 0.25f, 0.80f, 0.00f, 0.24f, 0.84f, 0.64f, 0.00f, 0.70f, 0.00f},
- {0.00f, 0.46f, 0.00f, 0.69f, 0.12f, 0.00f, 0.18f, 0.10f, 0.27f, 0.15f, 0.00f, 0.00f,
- 0.16f, 0.00f, 0.24f, 0.00f, 0.00f, 0.44f, 0.60f, 1.40f, 1.20f, 2.80f, 1.08f, 2.52f,
- 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.35f, 0.00f, 0.70f, 0.00f, 0.63f, 0.00f},
- {0.00f, 0.46f, 0.27f, 0.15f, 0.00f, 0.44f, 0.60f, 1.40f, 0.00f, 0.00f, 0.63f, 0.00f}};
- std::vector<float> input1_data{-0.3f, 2.3f, 0.9f, 0.5f, 0.8f, -1.1f,
- 1.2f, 2.8f, -1.6f, 0.0f, 0.7f, -2.2f};
- std::vector<float> input2_data{0.2f, 0.3f, -0.4f, 0.5f, 1.0f, 0.9f};
- for (size_t i = 0; i < test_shapes.size(); ++i)
- {
- Tensor input1_tensor =
- makeInputTensor<DataType::FLOAT32>(base_shape, input1_data, _memory_manager.get());
- Tensor input2_tensor =
- makeInputTensor<DataType::FLOAT32>(test_shapes[i], input2_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- MulParams params{};
- params.activation = Activation::RELU;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- Mul kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 2);
- EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(test_outputs[i], 0.0001f))
- << "With shape number " << i;
+ // set left input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
}
- // Re-run with exchanged inputs.
- for (size_t i = 0; i < test_shapes.size(); ++i)
+
+ // set right input data
{
- Tensor input1_tensor =
- makeInputTensor<DataType::FLOAT32>(test_shapes[i], input2_data, _memory_manager.get());
- Tensor input2_tensor =
- makeInputTensor<DataType::FLOAT32>(base_shape, input1_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(1));
+ std::copy(test_data_base->get_input_data_by_index(1).begin(),
+ test_data_base->get_input_data_by_index(1).end(), input_tensor_data);
+ }
- MulParams params{};
- params.activation = Activation::RELU;
+ runtime_module.execute();
- Mul kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
- EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(test_outputs[i], 0.0001f))
- << "With shape number " << i;
- }
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-template <loco::DataType DType> void checkInteger(luci_interpreter::IMemoryManager *memory_manager)
+TEST_F(MulTest, Float_P)
{
- using dtype = typename loco::DataTypeImpl<DType>::Type;
- Shape base_shape = {2, 3, 1, 2};
- std::vector<Shape> test_shapes{{1, 1, 3, 2}, {1, 3, 1, 2}, {2, 1, 3, 1}, {2, 3, 1, 1}};
-
- dtype max_value = std::numeric_limits<dtype>::max();
- dtype res_max = max_value - max_value % 10;
-
- std::vector<std::vector<dtype>> test_outputs = {
- {8, 0, 20, 0, 4, 30, //
- 16, 0, 40, 3, 8, 0, //
- 0, 0, 0, 6, 0, 0, //
- 4, 0, 10, 9, 2, 0, //
- 40, 0, 100, 0, 20, 150, //
- 28, 0, 70, 0, 14, res_max},
- {8, 0, 40, 3, 0, 0, 4, 0, 100, 0, 14, res_max},
- {8, 12, 0, 0, 20, 30, 16, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0,
- 0, 0, 9, 2, 0, 10, 0, 0, 0, 20, 30, 100, 150, 0, 0, 14, max_value / 10 * 2,
- 70, res_max},
- {8, 12, 0, 0, 0, 0, 0, 9, 20, 30, 70, res_max}};
- std::vector<dtype> input1_data{2, 3, 4, -1, -3, -2, 1, -3, 10, 15, 7, max_value / 10};
- std::vector<dtype> input2_data{4, 0, 10, -3, 2, 10};
- for (size_t i = 0; i < test_shapes.size(); ++i)
+ // No broadcast
{
- Tensor input1_tensor = makeInputTensor<DType>(base_shape, input1_data, memory_manager);
- Tensor input2_tensor = makeInputTensor<DType>(test_shapes[i], input2_data, memory_manager);
- Tensor output_tensor = makeOutputTensor(DType);
-
- MulParams params{};
- params.activation = Activation::RELU;
-
- Mul kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<dtype>(output_tensor), test_outputs[i])
- << "With shape number " << i;
+ const bool is_with_broadcast = false;
+ test_kernel::TestDataFloatMul test_data_kernel(is_with_broadcast);
+ std::vector<float> output_data_vector = checkMulKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+ test_data_kernel.get_output_data_by_index(0), 0.0001f));
}
- // Re-run with exchanged inputs.
- for (size_t i = 0; i < test_shapes.size(); ++i)
+ // With broadcast
{
- Tensor input1_tensor = makeInputTensor<DType>(test_shapes[i], input2_data, memory_manager);
- Tensor input2_tensor = makeInputTensor<DType>(base_shape, input1_data, memory_manager);
- Tensor output_tensor = makeOutputTensor(DType);
-
- MulParams params{};
- params.activation = Activation::RELU;
-
- Mul kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<dtype>(output_tensor), test_outputs[i])
- << "With shape number " << i;
+ const bool is_with_broadcast = true;
+ test_kernel::TestDataFloatMul test_data_kernel(is_with_broadcast);
+ std::vector<float> output_data_vector = checkMulKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+ test_data_kernel.get_output_data_by_index(0), 0.0001f));
}
}
-TEST_F(MulTest, SInt64)
+TEST_F(MulTest, INT_P)
{
- checkInteger<loco::DataType::S64>(_memory_manager.get());
- SUCCEED();
-}
-
-TEST_F(MulTest, SInt32)
-{
- checkInteger<loco::DataType::S32>(_memory_manager.get());
- SUCCEED();
-}
-
-TEST_F(MulTest, SInt16)
-{
- Shape base_shape = {2, 3, 1, 2};
- std::vector<Shape> test_shapes{{1, 1, 3, 2}, {1, 3, 1, 2}, {2, 1, 3, 1}, {2, 3, 1, 1}};
- std::vector<std::vector<int32_t>> ref_output_shapes{
- {2, 3, 3, 2}, {2, 3, 1, 2}, {2, 3, 3, 2}, {2, 3, 1, 2}};
-
- std::vector<float> input1_data{-0.3f, 2.3f, 0.9f, 0.5f, 0.8f, -1.1f,
- 1.2f, 2.8f, -1.6f, 0.0f, 0.7f, -2.2f};
- std::vector<float> input2_data{0.2f, 0.3f, -0.4f, 0.5f, 1.0f, 0.9f};
- std::vector<std::vector<float>> ref_outputs = {
- {0.00f, 0.69f, 0.12f, 1.15f, 0.00f, 2.07f, 0.18f, 0.15f, 0.00f, 0.25f, 0.90f, 0.45f,
- 0.16f, 0.00f, 0.00f, 0.00f, 0.80f, 0.00f, 0.24f, 0.84f, 0.00f, 1.40f, 1.20f, 2.52f,
- 0.00f, 0.00f, 0.64f, 0.00f, 0.00f, 0.00f, 0.14f, 0.00f, 0.00f, 0.00f, 0.70f, 0.00f},
- {0.00f, 0.69f, 0.00f, 0.25f, 0.80f, 0.00f, 0.24f, 0.84f, 0.64f, 0.00f, 0.70f, 0.00f},
- {0.00f, 0.46f, 0.00f, 0.69f, 0.12f, 0.00f, 0.18f, 0.10f, 0.27f, 0.15f, 0.00f, 0.00f,
- 0.16f, 0.00f, 0.24f, 0.00f, 0.00f, 0.44f, 0.60f, 1.40f, 1.20f, 2.80f, 1.08f, 2.52f,
- 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.35f, 0.00f, 0.70f, 0.00f, 0.63f, 0.00f},
- {0.00f, 0.46f, 0.27f, 0.15f, 0.00f, 0.44f, 0.60f, 1.40f, 0.00f, 0.00f, 0.63f, 0.00f}};
- for (size_t i = 0; i < test_shapes.size(); ++i)
+ // No broadcast
{
- Tensor input1_tensor = makeInputTensor<DataType::S16>(base_shape, 3.0 / 32767, 0, input1_data,
- _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::S16>(test_shapes[i], 1.0 / 32767, 0,
- input2_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S16, 4.0 / 32767, 0);
- const float tolerance = output_tensor.scale() * 2;
-
- MulParams params{};
- params.activation = Activation::RELU;
-
- Mul kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor),
- ::testing::ElementsAreArray(ref_output_shapes[i]))
- << "With shape number " << i;
- EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_outputs[i], tolerance))
- << "With shape number " << i;
+ const bool is_with_broadcast = false;
+ test_kernel::TestDataIntMul test_data_kernel(is_with_broadcast);
+ const auto output_data_vector = checkMulKernel<int32_t>(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
- // Re-run with exchanged inputs and different scales.
- for (size_t i = 0; i < test_shapes.size(); ++i)
+ // With broadcast
{
- Tensor input1_tensor = makeInputTensor<DataType::S16>(test_shapes[i], 2.0 / 32767, 0,
- input2_data, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::S16>(base_shape, 4.0 / 32767, 0, input1_data,
- _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S16, 3.0 / 32767, 0);
- const float tolerance = output_tensor.scale() * 2;
-
- MulParams params{};
- params.activation = Activation::RELU;
-
- Mul kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor),
- ::testing::ElementsAreArray(ref_output_shapes[i]))
- << "With shape number " << i;
- EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_outputs[i], tolerance))
- << "With shape number " << i;
+ const bool is_with_broadcast = true;
+ test_kernel::TestDataIntMul test_data_kernel(is_with_broadcast);
+ const auto output_data_vector = checkMulKernel<int32_t>(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
}
-TEST_F(MulTest, Input_Output_Type_NEG)
+TEST_F(MulTest, Wrong_Input1_Type_NEG)
{
- Tensor input1_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::S32>({1}, {2}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- MulParams params{};
- params.activation = Activation::RELU;
-
- Mul kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::NegTestDataInput1WrongTypeMul test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST_F(MulTest, Invalid_Output_Type_NEG)
+TEST_F(MulTest, Wrong_Input2_Type_NEG)
{
- Tensor input1_tensor = makeInputTensor<DataType::S64>({1}, {1}, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::S64>({1}, {2}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S32);
-
- MulParams params{};
- params.activation = Activation::RELU;
-
- Mul kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::NegTestDataInput2WrongTypeMul test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST_F(MulTest, Invalid_Input_Type_NEG)
+TEST_F(MulTest, Wrong_Ouput_Type_NEG)
{
- Tensor input1_tensor = makeInputTensor<DataType::U64>({1}, {1}, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::U64>({1}, {2}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U64);
-
- MulParams params{};
- params.activation = Activation::RELU;
-
- Mul kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- EXPECT_ANY_THROW(kernel.execute());
+ test_kernel::NegTestDataInt16TypeMul test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST_F(MulTest, Invalid_Quantization_NEG)
-{
- Tensor input1_tensor = makeInputTensor<DataType::S16>({1}, {1}, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::S16>({1}, {2}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S16);
-
- MulParams params{};
- params.activation = Activation::NONE;
-
- Mul kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
-}
+// TODO: add tests for U8 and S16
+// TODO: add tests for inplace optimizations for all types
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Neg.cpp b/onert-micro/luci-interpreter/src/kernels/Neg.cpp
index eae787ae5..3f08df319 100644
--- a/onert-micro/luci-interpreter/src/kernels/Neg.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Neg.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,43 +14,66 @@
* limitations under the License.
*/
-#include "kernels/Neg.h"
+#include "Builders.h"
#include "kernels/Utils.h"
+#include "kernels/BinaryOpCommon.h"
+
#include "PALNeg.h"
namespace luci_interpreter
{
-namespace kernels
+void configure_kernel_CircleNeg(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
+ const auto input_index = cur_op->inputs()->operator[](0);
+ const auto output_index = cur_op->outputs()->operator[](0);
-Neg::Neg(const Tensor *input, Tensor *output) : Kernel({input}, {output}) {}
+ assert(input_index != -1);
+ assert(output_index != -1);
+
+ const auto input = runtime_graph->getCircleTensorByIndex(input_index);
+ const auto output = runtime_graph->getCircleTensorByIndex(output_index);
+
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(input) == Tensor::element_type(output));
+
+ assert(Tensor::num_dims(input) == 4);
-void Neg::configure()
-{
- LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
// TODO: enable it only if kernel with dynamic shapes
- output()->resize(input()->shape());
+ // output-> resize(input->shape());
}
-void Neg::execute() const
+void execute_kernel_CircleNeg(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- switch (input()->element_type())
+ const auto input_index = cur_op->inputs()->operator[](0);
+ const auto output_index = cur_op->outputs()->operator[](0);
+
+ assert(input_index != -1);
+ assert(output_index != -1);
+
+ const auto input = runtime_graph->getCircleTensorByIndex(input_index);
+ const auto output = runtime_graph->getCircleTensorByIndex(output_index);
+
+ const uint8_t *input_data = runtime_graph->getDataByTensor(input);
+ uint8_t *output_data = runtime_graph->getDataByTensor(output);
+
+ assert(input_data != nullptr);
+ assert(output_data != nullptr);
+
+ switch (Tensor::element_type(input))
{
+#ifndef DIS_FLOAT
case DataType::FLOAT32:
- evalFloat();
+
+ luci_interpreter_pal::Negate(
+ kernels::getTensorShape(input), kernels::getTensorData<float>(input_data),
+ kernels::getTensorShape(output), kernels::getTensorData<float>(output_data));
+
break;
+#endif // DIS_FLOAT
default:
assert(false && "Unsupported type.");
}
}
-void Neg::evalFloat() const
-{
- luci_interpreter_pal::Negate(getTensorShape(input()), getTensorData<float>(input()),
- getTensorShape(output()), getTensorData<float>(output()));
-}
-
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Neg.h b/onert-micro/luci-interpreter/src/kernels/Neg.h
deleted file mode 100644
index f5f565df1..000000000
--- a/onert-micro/luci-interpreter/src/kernels/Neg.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_NEG_H
-#define LUCI_INTERPRETER_KERNELS_NEG_H
-
-#include "core/Kernel.h"
-#include <vector>
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Neg : public Kernel
-{
-public:
- Neg(const Tensor *input, Tensor *output);
-
- const Tensor *input() const { return _inputs[0]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-
-private:
- void evalFloat() const;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_NEG_H
diff --git a/onert-micro/luci-interpreter/src/kernels/Neg.test.cpp b/onert-micro/luci-interpreter/src/kernels/Neg.test.cpp
index 8b2bc1a82..0cb0a272b 100644
--- a/onert-micro/luci-interpreter/src/kernels/Neg.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Neg.test.cpp
@@ -15,57 +15,86 @@
* limitations under the License.
*/
-#include "kernels/Neg.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/neg/FloatNegKernel.h"
+#include "luci_interpreter/test_models/neg/NegNegKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
using namespace testing;
-template <typename T>
-void Check(std::initializer_list<int32_t> input_shape, std::initializer_list<int32_t> output_shape,
- std::initializer_list<T> input_data, std::initializer_list<T> output_data)
+class NegTest : public ::testing::Test
+{
+ // Do nothing
+};
+
+template <typename T> std::vector<T> checkNegKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- constexpr DataType element_type = getElementType<T>();
- Tensor input_tensor =
- makeInputTensor<element_type>(input_shape, input_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(element_type);
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- Neg kernel(&input_tensor, &output_tensor);
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
- EXPECT_THAT(extractTensorData<T>(output_tensor), ::testing::ElementsAreArray(output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
+
+ runtime_module.execute();
+
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
+
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST(NegTest, FloatSimple)
+TEST_F(NegTest, Float_P)
{
- Check<float>(/*input_shape=*/{2, 3},
- /*output_shape=*/{2, 3},
- /*input_data=*/
- {
- 0.0f, 1.0f, 3.0f, // Row 1
- 1.0f, -1.0f, -2.0f, // Row 2
- },
- /*output_data=*/
- {
- 0.0f, -1.0f, -3.0f, // Row 1
- -1.0f, 1.0f, 2.0f, // Row 2
- });
-
- SUCCEED();
+ test_kernel::TestDataFloatNeg test_data_kernel;
+ std::vector<float> output_data_vector = checkNegKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(NegTest, Input_output_type_mismatch_NEG)
+{
+ test_kernel::NegTestDataInputOutputTypeMismatchNegKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
+}
+
+TEST_F(NegTest, Invalid_input_shape_NEG)
+{
+ test_kernel::NegTestDataInvalidInputShapeNegKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/NotEqual.cpp b/onert-micro/luci-interpreter/src/kernels/NotEqual.cpp
index 304939ee8..92f646f95 100644
--- a/onert-micro/luci-interpreter/src/kernels/NotEqual.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/NotEqual.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,128 +14,76 @@
* limitations under the License.
*/
-#include "kernels/NotEqual.h"
+#include "Builders.h"
#include "kernels/Utils.h"
+#include "TISOKernel.h"
-#include <tensorflow/lite/kernels/internal/reference/comparisons.h>
+#include "PALComparisons.h"
namespace luci_interpreter
{
-namespace kernels
+namespace
{
+// TODO: reduce code duplication with less
+template <typename T>
+void evalGeneric(const circle::Tensor *x, const circle::Tensor *y, const circle::Tensor *output,
+ BaseRuntimeGraph *runtime_graph)
+{
+ auto x_data = kernels::getTensorData<T>(runtime_graph->getDataByTensor(x));
+ if (x_data == nullptr)
+ x_data = kernels::getTensorData<T>(runtime_graph->getConstDataByTensor(x));
+
+ assert(x_data != nullptr);
+
+ auto y_data = kernels::getTensorData<T>(runtime_graph->getDataByTensor(y));
+ if (y_data == nullptr)
+ y_data = kernels::getTensorData<T>(runtime_graph->getConstDataByTensor(y));
+
+ assert(y_data != nullptr);
+
+ auto output_data = kernels::getTensorData<bool>(runtime_graph->getDataByTensor(output));
-NotEqual::NotEqual(const Tensor *x, const Tensor *y, Tensor *output) : Kernel({x, y}, {output}) {}
+ luci_interpreter_pal::ComparisonParams op_params;
+ op_params.is_broadcast = Tensor::num_elements(x) != Tensor::num_elements(y);
-void NotEqual::configure()
+ const int64_t flat_size = kernels::getTensorShape(x).flatSize();
+ luci_interpreter_pal::ComparisonNoScaling<T>(flat_size, x_data, y_data, output_data,
+ luci_interpreter_pal::NotEqualFn);
+}
+
+} // namespace
+
+void configure_kernel_CircleNotEqual(const circle::Operator *cur_op,
+ BaseRuntimeGraph *runtime_graph)
{
- LUCI_INTERPRETER_CHECK(x()->element_type() == y()->element_type());
- LUCI_INTERPRETER_CHECK(output()->element_type() == DataType::BOOL);
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
- if (x()->element_type() == DataType::U8)
- {
- quantizeMultiplierSmallerThanOneExp(x()->scale(), &_x_multiplier, &_x_shift);
- quantizeMultiplierSmallerThanOneExp(y()->scale(), &_y_multiplier, &_y_shift);
- }
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(calculateShapeForBroadcast(x()->shape(), y()->shape()));
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+ Tensor::element_type(kernel.input2()));
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.output()) == DataType::BOOL);
}
-void NotEqual::execute() const
+void execute_kernel_CircleNotEqual(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- switch (x()->element_type())
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
+
+ switch (Tensor::element_type(kernel.input1()))
{
- case DataType::FLOAT32:
- evalFloat();
- break;
case DataType::S64:
- evalInteger<int64_t>();
+ evalGeneric<int64_t>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
break;
case DataType::S32:
- evalInteger<int32_t>();
+ evalGeneric<int32_t>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
break;
- case DataType::U8:
- evalQuantized();
+#ifndef DIS_FLOAT
+ case DataType::FLOAT32:
+ evalGeneric<float>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
break;
+#endif // DIS_FLOAT
default:
assert(false && "Unsupported type.");
}
}
-void NotEqual::evalFloat() const
-{
- const auto x_data = getTensorData<float>(x());
- const auto y_data = getTensorData<float>(y());
- auto output_data = getTensorData<bool>(output());
-
- tflite::ComparisonParams op_params;
- op_params.is_broadcast = x()->shape() != y()->shape();
-
- if (op_params.is_broadcast)
- {
- tflite::reference_ops::Broadcast4DSlowNotEqual(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data,
- getTensorShape(output()), output_data);
- }
- else
- {
- tflite::reference_ops::NotEqual(op_params, getTensorShape(x()), x_data, getTensorShape(y()),
- y_data, getTensorShape(output()), output_data);
- }
-}
-
-template <typename T> void NotEqual::evalInteger() const
-{
- const auto x_data = getTensorData<T>(x());
- const auto y_data = getTensorData<T>(y());
- auto output_data = getTensorData<bool>(output());
-
- tflite::ComparisonParams op_params;
- op_params.is_broadcast = x()->shape() != y()->shape();
-
- if (op_params.is_broadcast)
- {
- tflite::reference_ops::Broadcast4DSlowNotEqualNoScaling(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data,
- getTensorShape(output()), output_data);
- }
- else
- {
- tflite::reference_ops::NotEqualNoScaling(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data, getTensorShape(output()),
- output_data);
- }
-}
-
-void NotEqual::evalQuantized() const
-{
- const auto x_data = getTensorData<uint8_t>(x());
- const auto y_data = getTensorData<uint8_t>(y());
- auto output_data = getTensorData<bool>(output());
-
- tflite::ComparisonParams op_params;
- op_params.left_shift = 8;
- op_params.input1_offset = -x()->zero_point(); // Note the '-'
- op_params.input1_shift = _x_shift;
- op_params.input1_multiplier = _x_multiplier;
- op_params.input2_offset = -y()->zero_point(); // Note the '-'
- op_params.input2_shift = _y_shift;
- op_params.input2_multiplier = _y_multiplier;
- op_params.is_broadcast = x()->shape() != y()->shape();
-
- if (op_params.is_broadcast)
- {
- tflite::reference_ops::Broadcast4DSlowNotEqualWithScaling(
- op_params, getTensorShape(x()), x_data, getTensorShape(y()), y_data, getTensorShape(output()),
- output_data);
- }
- else
- {
- tflite::reference_ops::NotEqualWithScaling(op_params, getTensorShape(x()), x_data,
- getTensorShape(y()), y_data,
- getTensorShape(output()), output_data);
- }
-}
-
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/NotEqual.h b/onert-micro/luci-interpreter/src/kernels/NotEqual.h
deleted file mode 100644
index baa22a679..000000000
--- a/onert-micro/luci-interpreter/src/kernels/NotEqual.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_NOT_EQUAL_H
-#define LUCI_INTERPRETER_KERNELS_NOT_EQUAL_H
-
-#include "core/Kernel.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class NotEqual : public Kernel
-{
-public:
- NotEqual(const Tensor *x, const Tensor *y, Tensor *output);
-
- const Tensor *x() const { return _inputs[0]; }
- const Tensor *y() const { return _inputs[1]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-
-private:
- void evalFloat() const;
- template <typename T> void evalInteger() const;
- void evalQuantized() const;
-
-private:
- int32_t _x_multiplier = 0;
- int _x_shift = 0;
- int32_t _y_multiplier = 0;
- int _y_shift = 0;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_NOT_EQUAL_H
diff --git a/onert-micro/luci-interpreter/src/kernels/NotEqual.test.cpp b/onert-micro/luci-interpreter/src/kernels/NotEqual.test.cpp
index 45bf4022a..520a02ea5 100644
--- a/onert-micro/luci-interpreter/src/kernels/NotEqual.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/NotEqual.test.cpp
@@ -15,14 +15,13 @@
* limitations under the License.
*/
-#include "kernels/NotEqual.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/notequal/FloatNotEqualKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
@@ -30,277 +29,61 @@ using namespace testing;
class NotEqualTest : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-TEST_F(NotEqualTest, FloatSimple)
-{
- std::vector<float> x_data{
- 0.5, 0.7, 0.9, // Row 1
- 1, 0, -1, // Row 2
- };
-
- std::vector<float> y_data{
- 0.9, 0.7, 0.5, // Row 1
- -1, 0, 1, // Row 2
- };
-
- std::vector<bool> ref_output_data{
- true, false, true, // Row 1
- true, false, true, // Row 2
- };
-
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- NotEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({2, 3}));
-}
-
-TEST_F(NotEqualTest, FloatBroardcast)
-{
- std::vector<float> x_data{
- 0.5, 0.7, 0.9, // Row 1
- 1, 0, -1, // Row 2
- -1, 0, 1, // Row 3
- 0.9, 0.7, 0.5, // Row 4
- };
-
- std::vector<float> y_data{
- 0.9, 0.7, 0.5, // Row 1
- };
-
- std::vector<bool> ref_output_data{
- true, false, true, // Row 1
- true, true, true, // Row 2
- true, true, true, // Row 3
- false, false, false, // Row 4
- };
-
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({4, 3}, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({1, 3}, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- NotEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({4, 3}));
-}
-
-template <loco::DataType DType>
-void checkIntegerSimple(luci_interpreter::IMemoryManager *memory_manager)
-{
- using dtype = typename loco::DataTypeImpl<DType>::Type;
- dtype min_value = std::numeric_limits<dtype>::min();
- dtype max_value = std::numeric_limits<dtype>::max();
- std::vector<dtype> x_data{min_value, 2, max_value};
-
- std::vector<dtype> y_data{min_value, -2, max_value};
-
- std::vector<bool> ref_output_data{false, true, false};
-
- Tensor x_tensor = makeInputTensor<DType>({3}, x_data, memory_manager);
- Tensor y_tensor = makeInputTensor<DType>({3}, y_data, memory_manager);
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- NotEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({3}));
-}
-
-template <loco::DataType DType>
-void checkIntegerBroadcast(luci_interpreter::IMemoryManager *memory_manager)
-{
- using dtype = typename loco::DataTypeImpl<DType>::Type;
- dtype min_value = std::numeric_limits<dtype>::min();
- dtype max_value = std::numeric_limits<dtype>::max();
- std::vector<dtype> x_data{
- min_value, 2, 3, // Row 1
- 4, 5, max_value, // Row 2
- -1, -2, -3, // Row 3
- min_value, -2, max_value, // Row 4
- };
-
- std::vector<dtype> y_data{
- min_value, -2, max_value, // Row 1
- };
-
- std::vector<bool> ref_output_data{
- false, true, true, // Row 1
- true, true, false, // Row 2
- true, false, true, // Row 3
- false, false, false, // Row 4
- };
-
- Tensor x_tensor = makeInputTensor<DType>({4, 3}, x_data, memory_manager);
- Tensor y_tensor = makeInputTensor<DType>({3}, y_data, memory_manager);
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- NotEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({4, 3}));
-}
-
-TEST_F(NotEqualTest, Int32)
-{
- checkIntegerSimple<loco::DataType::S32>(_memory_manager.get());
- checkIntegerBroadcast<loco::DataType::S32>(_memory_manager.get());
- SUCCEED();
-}
-
-TEST_F(NotEqualTest, Int64)
-{
- checkIntegerSimple<loco::DataType::S64>(_memory_manager.get());
- checkIntegerBroadcast<loco::DataType::S64>(_memory_manager.get());
- SUCCEED();
-}
-
-// Choose min / max in such a way that there are exactly 256 units to avoid rounding errors.
-const float F_MIN = -128.0 / 128.0;
-const float F_MAX = 127.0 / 128.0;
-
-TEST_F(NotEqualTest, Uint8Quantized)
-{
- std::vector<float> x_data{
- 0.5, 0.5, 0.7, 0.9, // Row 1
- 1, 0, 0.05, -1, // Row 2
- };
-
- std::vector<float> y_data{
- 0.9, 0.5, 0.55, 0.5, // Row 1
- -1, 0, 0.05, 1, // Row 2
- };
-
- std::vector<bool> ref_output_data{
- true, false, true, true, // Row 1
- true, false, false, true, // Row 2
- };
-
- std::pair<float, int32_t> x_quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
- Tensor x_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, x_quant_param.first, x_quant_param.second, x_data, _memory_manager.get());
-
- std::pair<float, int32_t> y_quant_param = quantizationParams<uint8_t>(F_MIN * 2, F_MAX * 2);
- Tensor y_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, y_quant_param.first, y_quant_param.second, y_data, _memory_manager.get());
-
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- NotEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 4, 1}));
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
-}
-
-TEST_F(NotEqualTest, Uint8QuantizedBroadcast)
+template <typename T, typename U>
+std::vector<U> checkNotEqualKernel(test_kernel::TestDataBase<T, U> *test_data_base)
{
- std::vector<float> x_data{
- 0.4, -0.8, 0.7, 0.3, // Row 1
- -0.5, 0.1, 0, 0.5, // Row 2
- 1, 0, 0.05, -1, // Row 3
- -1, 0.05, 0, 1, // Row 4
- };
-
- std::vector<float> y_data{
- -1, 0.05, 0, 1, // Row 1
- };
-
- std::vector<bool> ref_output_data{
- true, true, true, true, // Row 1
- true, true, false, true, // Row 2
- true, true, true, true, // Row 3
- false, false, false, false, // Row 4
- };
-
- std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
- Tensor x_tensor = makeInputTensor<DataType::U8>(
- {1, 4, 4, 1}, quant_param.first, quant_param.second, x_data, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::U8>(
- {1, 1, 4, 1}, quant_param.first, quant_param.second, y_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- NotEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 4, 4, 1}));
- EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
-}
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
-TEST_F(NotEqualTest, Input_Type_Mismatch_NEG)
-{
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::U8>({1}, {1}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 2);
- NotEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
-}
+ // set left input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
-TEST_F(NotEqualTest, Input_Output_Type_NEG)
-{
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+ // set right input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(1));
+ std::copy(test_data_base->get_input_data_by_index(1).begin(),
+ test_data_base->get_input_data_by_index(1).end(), input_tensor_data);
+ }
- NotEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
-}
+ runtime_module.execute();
-TEST_F(NotEqualTest, Float_Broadcast_NEG)
-{
- Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({2}, {1.f, 2.f}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({3}, {1.f, 2.f, 3.f}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
- NotEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- ASSERT_ANY_THROW(kernel.configure());
+ U *output_data = reinterpret_cast<U *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(U));
+ std::vector<U> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST_F(NotEqualTest, Int32_Broadcast_NEG)
+TEST_F(NotEqualTest, FloatNoBroadcast_P)
{
- Tensor x_tensor = makeInputTensor<DataType::S32>({2}, {1, 2}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::S32>({3}, {1, 2, 3}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- NotEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- ASSERT_ANY_THROW(kernel.configure());
+ const bool is_with_broadcast = false;
+ test_kernel::TestDataFloatNotEqual test_data_kernel(is_with_broadcast, false);
+ std::vector<bool> output_data_vector = checkNotEqualKernel<float, bool>(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-TEST_F(NotEqualTest, Int64_Broadcast_NEG)
+TEST_F(NotEqualTest, FloatNoBroadcast_NEG)
{
- Tensor x_tensor = makeInputTensor<DataType::S64>({2}, {1, 2}, _memory_manager.get());
- Tensor y_tensor = makeInputTensor<DataType::S64>({3}, {1, 2, 3}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
- NotEqual kernel(&x_tensor, &y_tensor, &output_tensor);
- ASSERT_ANY_THROW(kernel.configure());
+ const bool is_with_broadcast = false;
+ test_kernel::TestDataFloatNotEqual test_data_kernel(is_with_broadcast, true);
+ EXPECT_DEATH(checkNotEqualKernel(&test_data_kernel), "");
}
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/OneHot.h b/onert-micro/luci-interpreter/src/kernels/OneHot.h
index f1afc2871..572f857ae 100644
--- a/onert-micro/luci-interpreter/src/kernels/OneHot.h
+++ b/onert-micro/luci-interpreter/src/kernels/OneHot.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/OneHot.test.cpp b/onert-micro/luci-interpreter/src/kernels/OneHot.test.cpp
index bc59d2295..45b6968fa 100644
--- a/onert-micro/luci-interpreter/src/kernels/OneHot.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/OneHot.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/PRelu.cpp b/onert-micro/luci-interpreter/src/kernels/PRelu.cpp
index c3c79be7d..3d64215c5 100644
--- a/onert-micro/luci-interpreter/src/kernels/PRelu.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/PRelu.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/PRelu.h b/onert-micro/luci-interpreter/src/kernels/PRelu.h
index b62cc2a75..f7735d418 100644
--- a/onert-micro/luci-interpreter/src/kernels/PRelu.h
+++ b/onert-micro/luci-interpreter/src/kernels/PRelu.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Pack.cpp b/onert-micro/luci-interpreter/src/kernels/Pack.cpp
index 62228f16d..7277f2293 100644
--- a/onert-micro/luci-interpreter/src/kernels/Pack.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Pack.cpp
@@ -15,126 +15,114 @@
* limitations under the License.
*/
-#include "kernels/Pack.h"
-#include "kernels/Utils.h"
+#include "Builders.h"
+#include "Utils.h"
-#include <tensorflow/lite/kernels/internal/reference/reference_ops.h>
+#include <cassert>
namespace luci_interpreter
{
-namespace kernels
+namespace
{
-Pack::Pack(std::vector<const Tensor *> inputs, Tensor *output, const PackParams &params)
- : KernelWithParams<PackParams>(std::move(inputs), {output}, params)
+template <typename T>
+void packImpl(const circle::Tensor *input0, const circle::Tensor *output,
+ const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph,
+ uint8_t *output_data_raw)
{
-}
+ const auto *options = cur_op->builtin_options_as_PackOptions();
+
+ const int values_count = options->values_count();
+ int axis = options->axis();
+ const int dimensions = Tensor::num_dims(output);
+
+ const auto input_dims = wrap(input0->shape());
+ const auto output_dims = wrap(output->shape());
-void Pack::configure()
-{
- LUCI_INTERPRETER_CHECK(_inputs.size() == static_cast<uint32_t>(params().values_count));
- const Tensor *t0 = _inputs[0];
- const int dimension_size = t0->shape().num_dims() + 1;
- int axis = params().axis;
if (axis < 0)
{
- axis += dimension_size;
+ axis += dimensions;
}
- LUCI_INTERPRETER_CHECK(axis >= 0 && axis <= t0->shape().num_dims());
- if (t0->element_type() != DataType::S32 && t0->element_type() != DataType::FLOAT32 &&
- t0->element_type() != DataType::U8 && t0->element_type() != DataType::S8 &&
- t0->element_type() != DataType::S16 && t0->element_type() != DataType::S64)
- {
- assert(false && "Unsupported type.");
- }
+ int outer_size = 1;
+ for (int i = 0; i < axis; ++i)
+ outer_size *= output_dims[i];
- for (uint32_t i = 1; i < _inputs.size(); ++i)
- {
- const Tensor *tensor = _inputs[i];
- LUCI_INTERPRETER_CHECK(tensor->element_type() == t0->element_type());
- LUCI_INTERPRETER_CHECK(tensor->shape().num_dims() == t0->shape().num_dims());
- for (int d = 0; d < t0->shape().num_dims(); ++d)
- {
- LUCI_INTERPRETER_CHECK(tensor->shape().dim(d) == t0->shape().dim(d));
- }
- }
+ int copy_size = 1;
+ for (int i = axis + 1; i < dimensions; ++i)
+ copy_size *= output_dims[i];
- Shape output_shape(dimension_size);
- int i = 0;
- for (int index = 0; index < dimension_size; ++index)
- {
- if (index == axis)
- {
- output_shape.dim(index) = params().values_count;
- }
- else
- {
- output_shape.dim(index) = t0->shape().dim(i++);
- }
- }
+ int input_size = 1;
+ for (int i = 0; i < input_dims.size(); ++i)
+ input_size *= input_dims[i];
+
+ assert(input_size == copy_size * outer_size);
+
+ T *output_data = kernels::getTensorData<T>(output_data_raw);
+ assert(output_data != nullptr);
- if (t0->element_type() == DataType::U8 || t0->element_type() == DataType::S8 ||
- t0->element_type() == DataType::S16)
+ for (int i = 0; i < values_count; ++i)
{
- LUCI_INTERPRETER_CHECK(output()->zero_point() == t0->zero_point());
- LUCI_INTERPRETER_CHECK(output()->scale() == t0->scale());
- // Guarantee input/output quantization params match as we do not support
- // packing quantized tensors.
- for (int i = 0; i < params().values_count; i++)
+ const auto input_index = cur_op->inputs()->operator[](i);
+ assert(input_index != -1);
+ const auto input = runtime_graph->getCircleTensorByIndex(input_index);
+
+ auto input_data = kernels::getTensorData<T>(runtime_graph->getDataByTensor(input));
+ assert(input_data != nullptr);
+ for (int k = 0; k < outer_size; ++k)
{
- LUCI_INTERPRETER_CHECK(_inputs[i]->zero_point() == t0->zero_point());
- LUCI_INTERPRETER_CHECK(_inputs[i]->scale() == t0->scale());
+ const T *input_ptr = input_data + copy_size * k;
+ int loc = k * values_count * copy_size + i * copy_size;
+ T *output_ptr = output_data + loc;
+ for (int j = 0; j < copy_size; ++j)
+ output_ptr[j] = input_ptr[j];
}
}
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(output_shape);
}
-void Pack::execute() const
+} // namespace
+
+void configure_kernel_CirclePack(const circle::Operator *, BaseRuntimeGraph *)
+{
+ // Do nothing
+}
+
+void execute_kernel_CirclePack(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- switch (_inputs[0]->element_type())
+ const auto input_index = cur_op->inputs()->operator[](0);
+ const auto output_index = cur_op->outputs()->operator[](0);
+ assert(output_index != -1);
+ assert(input_index != -1);
+ const auto input = runtime_graph->getCircleTensorByIndex(input_index);
+ const auto output = runtime_graph->getCircleTensorByIndex(output_index);
+
+ auto output_data = runtime_graph->getDataByTensor(output);
+ assert(output_data != nullptr);
+
+ switch (Tensor::element_type(output))
{
+#ifndef DIS_FLOAT
case DataType::FLOAT32:
- evalGeneric<float>();
- break;
- case DataType::U8:
- evalGeneric<uint8_t>();
+ packImpl<float>(input, output, cur_op, runtime_graph, output_data);
break;
+#endif // DIS_FLOAT
+#ifndef DIS_QUANT
case DataType::S8:
- evalGeneric<int8_t>();
+ packImpl<int8_t>(input, output, cur_op, runtime_graph, output_data);
break;
- case DataType::S16:
- evalGeneric<int16_t>();
+ case DataType::U8:
+ packImpl<uint8_t>(input, output, cur_op, runtime_graph, output_data);
break;
+#endif // DIS_QUANT
case DataType::S32:
- evalGeneric<int32_t>();
+ packImpl<int32_t>(input, output, cur_op, runtime_graph, output_data);
break;
case DataType::S64:
- evalGeneric<int64_t>();
+ packImpl<int64_t>(input, output, cur_op, runtime_graph, output_data);
break;
default:
- assert(false && "Unsupported type.");
- }
-}
-
-template <typename T> void Pack::evalGeneric() const
-{
- const Tensor *t0 = _inputs[0];
- const int dimension_size = t0->shape().num_dims() + 1;
- int axis = params().axis;
- if (axis < 0)
- {
- axis += dimension_size;
+ assert(false && "Unsupported types");
}
-
- VectorOfTensors<T, true> inputs(_inputs);
- tflite::PackParams params{};
- params.axis = axis;
- params.inputs_count = _inputs.size();
- tflite::reference_ops::Pack<T>(params, inputs.shapes(), inputs.data(), getTensorShape(output()),
- getTensorData<T>(output()));
}
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Pack.h b/onert-micro/luci-interpreter/src/kernels/Pack.h
deleted file mode 100644
index 730177b44..000000000
--- a/onert-micro/luci-interpreter/src/kernels/Pack.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_PACK_H
-#define LUCI_INTERPRETER_KERNELS_PACK_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Pack : public KernelWithParams<PackParams>
-{
-public:
- Pack(std::vector<const Tensor *> inputs, Tensor *output, const PackParams &params);
-
- const Tensor *input(int index) const { return _inputs[index]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-
-private:
- template <typename T> void evalGeneric() const;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_PACK_H
diff --git a/onert-micro/luci-interpreter/src/kernels/Pack.test.cpp b/onert-micro/luci-interpreter/src/kernels/Pack.test.cpp
index cd5cff9db..db820b5e8 100644
--- a/onert-micro/luci-interpreter/src/kernels/Pack.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Pack.test.cpp
@@ -1,6 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,150 +14,82 @@
* limitations under the License.
*/
-#include "kernels/Pack.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/pack/PackKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
using namespace testing;
-template <typename T>
-void Check(std::vector<std::initializer_list<int32_t>> input_shapes,
- std::initializer_list<int32_t> output_shape, std::vector<std::vector<T>> input_datas,
- std::initializer_list<T> output_data, int32_t axis)
+class PackTest : public ::testing::Test
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- constexpr DataType element_type = getElementType<T>();
- std::vector<const Tensor *> inputs(input_datas.size());
- std::vector<Tensor> tmp_inputs;
- for (int i = 0; i < input_datas.size(); i++)
- {
- if (std::is_same<T, float>::value || std::is_same<T, int32_t>::value ||
- std::is_same<T, int64_t>::value)
- {
- tmp_inputs.push_back(Tensor(element_type, input_shapes[i], {}, ""));
- memory_manager->allocate_memory(tmp_inputs[i]);
- tmp_inputs[i].writeData(input_datas[i].data(), input_datas[i].size() * sizeof(T));
- }
- else if (std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value)
- {
- tmp_inputs.push_back(Tensor(element_type, input_shapes[i], {{1.0f / 255}, {128}}, ""));
- memory_manager->allocate_memory(tmp_inputs[i]);
- tmp_inputs[i].writeData(input_datas[i].data(), input_datas[i].size() * sizeof(T));
- }
- else
- {
- assert((std::is_same<T, int16_t>::value) && "unexpected dtype is tested");
- tmp_inputs.push_back(Tensor(element_type, input_shapes[i], {{1.0f}, {0}}, ""));
- memory_manager->allocate_memory(tmp_inputs[i]);
- tmp_inputs[i].writeData(input_datas[i].data(), input_datas[i].size() * sizeof(T));
- }
- }
- for (int i = 0; i < input_datas.size(); i++)
- {
- inputs[i] = &tmp_inputs[i];
- }
+ // Do nothing
+};
+
+template <typename T> std::vector<T> checkPackKernel(test_kernel::TestDataBase<T> *test_data_base)
+{
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- Tensor output_tensor = makeOutputTensor(element_type);
- if (std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value)
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
+
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 2);
+
+ // Set input 1 data
{
- output_tensor = makeOutputTensor(element_type, 1.0f / 255, 128);
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
}
- else if (std::is_same<T, int16_t>::value)
+
+ // Set input 2 data
{
- output_tensor = makeOutputTensor(element_type, 1.0f, 0);
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(1));
+ std::copy(test_data_base->get_input_data_by_index(1).begin(),
+ test_data_base->get_input_data_by_index(1).end(), input_tensor_data);
}
- PackParams params{};
- params.axis = axis;
- params.values_count = input_datas.size();
- Pack kernel(inputs, &output_tensor, params);
+ runtime_module.execute();
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
- EXPECT_THAT(extractTensorData<T>(output_tensor), ::testing::ElementsAreArray(output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-template <typename T> class PackTest : public ::testing::Test
+TEST_F(PackTest, Float_P)
{
-};
-
-using DataTypes = ::testing::Types<uint8_t, int8_t, int16_t, int32_t, int64_t, float>;
-TYPED_TEST_SUITE(PackTest, DataTypes);
-
-TYPED_TEST(PackTest, ThreeInputs)
-{
- Check<TypeParam>(/*input_shapes=*/{{2}, {2}, {2}},
- /*output_shape=*/{3, 2},
- /*input_datas=*/
- {{1, 4}, {2, 5}, {3, 6}},
- /*output_data=*/
- {1, 4, 2, 5, 3, 6}, /*axis=*/0);
-
- SUCCEED();
+ test_kernel::TestDataFloatPack test_data_pack_kernel;
+ std::vector<float> output_data_vector = checkPackKernel(&test_data_pack_kernel);
+ EXPECT_THAT(output_data_vector, test_data_pack_kernel.get_output_data_by_index(0));
}
-TYPED_TEST(PackTest, NegAxis)
+TEST_F(PackTest, Int_P)
{
- Check<TypeParam>(/*input_shapes=*/{{2}, {2}, {2}},
- /*output_shape=*/{2, 3},
- /*input_datas=*/
- {{1, 4}, {2, 5}, {3, 6}},
- /*output_data=*/
- {1, 2, 3, 4, 5, 6}, /*axis=*/-1);
-
- SUCCEED();
+ test_kernel::TestDataIntPack test_data_pack_kernel;
+ std::vector<int32_t> output_data_vector = checkPackKernel(&test_data_pack_kernel);
+ EXPECT_THAT(output_data_vector, test_data_pack_kernel.get_output_data_by_index(0));
}
-TEST(Pack, MismatchingInputValuesCount_NEG)
+TEST_F(PackTest, QuantU8_P)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- std::vector<float> input1_data{1, 4};
- std::vector<float> input2_data{2, 5};
- std::vector<float> input3_data{3, 6};
- Tensor input1_tensor = makeInputTensor<DataType::FLOAT32>({2}, input1_data, memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::FLOAT32>({2}, input2_data, memory_manager.get());
- Tensor input3_tensor = makeInputTensor<DataType::FLOAT32>({2}, input3_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
- PackParams params{};
- {
- params.axis = 0;
- params.values_count = 2;
-
- Pack kernel({&input1_tensor, &input2_tensor, &input3_tensor}, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
- }
+ test_kernel::TestDataQuantU8Pack test_data_pack_kernel;
+ std::vector<uint8_t> output_data_vector = checkPackKernel(&test_data_pack_kernel);
+ EXPECT_THAT(output_data_vector, test_data_pack_kernel.get_output_data_by_index(0));
}
-TEST(Pack, InvalidInputAxis_NEG)
-{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- std::vector<float> input1_data{1, 4};
- std::vector<float> input2_data{2, 5};
- std::vector<float> input3_data{3, 6};
- Tensor input1_tensor = makeInputTensor<DataType::FLOAT32>({2}, input1_data, memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::FLOAT32>({2}, input2_data, memory_manager.get());
- Tensor input3_tensor = makeInputTensor<DataType::FLOAT32>({2}, input3_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
- PackParams params{};
- {
- params.axis = 2;
- params.values_count = 3;
-
- Pack kernel({&input1_tensor, &input2_tensor, &input3_tensor}, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
- }
-}
+// TODO: add negative tests?
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Pad.cpp b/onert-micro/luci-interpreter/src/kernels/Pad.cpp
index 9ae0f822d..18af756a6 100644
--- a/onert-micro/luci-interpreter/src/kernels/Pad.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Pad.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,101 +14,19 @@
* limitations under the License.
*/
-#include "kernels/Pad.h"
-
-#include "kernels/Utils.h"
-
-#include <tensorflow/lite/kernels/internal/reference/pad.h>
-
-#include <limits>
+#include "Builders.h"
+#include "PadCommon.h"
namespace luci_interpreter
{
-namespace kernels
-{
-
-Pad::Pad(const Tensor *input, const Tensor *paddings, Tensor *output)
- : Kernel({input, paddings}, {output})
-{
-}
-
-void Pad::configure()
+void configure_kernel_CirclePad(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- const Shape &input_shape = input()->shape();
- const int num_dims = input_shape.num_dims();
-
- if (num_dims > 4)
- assert(false && "Unsupported number of dimensions.");
-
- assert(output()->element_type() == input()->element_type());
- assert(paddings()->element_type() == DataType::S32);
- // Paddings shape should be [N, 2].
- assert(paddings()->shape().num_dims() == 2);
- assert(paddings()->shape().dim(0) == num_dims);
- assert(paddings()->shape().dim(1) == 2);
-
- Shape output_shape(num_dims);
- const auto *paddings_data = getTensorData<int32_t>(paddings());
- for (int i = 0; i < num_dims; ++i)
- {
- const int32_t padding_before = paddings_data[i * 2];
- const int32_t padding_after = paddings_data[i * 2 + 1];
- assert(padding_before >= 0 && padding_after >= 0);
- output_shape.dim(i) = input_shape.dim(i) + padding_before + padding_after;
- }
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(output_shape);
+ configure_kernel_CirclePadCommon(cur_op, runtime_graph);
}
-void Pad::execute() const
+void execute_kernel_CirclePad(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- const int num_dims = input()->shape().num_dims();
-
- tflite::PadParams params{};
- params.left_padding_count = num_dims;
- params.right_padding_count = num_dims;
-
- const auto *paddings_data = getTensorData<int32_t>(paddings());
- for (int i = num_dims - 1; i >= 0; --i)
- {
- params.left_padding[i] = paddings_data[i * 2];
- params.right_padding[i] = paddings_data[i * 2 + 1];
- }
-
- switch (input()->element_type())
- {
- case DataType::FLOAT32:
- {
- const float pad_value = 0.0f;
- tflite::reference_ops::Pad(params, getTensorShape(input()), getTensorData<float>(input()),
- &pad_value, getTensorShape(output()),
- getTensorData<float>(output()));
- break;
- }
- case DataType::U8:
- {
- assert(output()->zero_point() >= std::numeric_limits<uint8_t>::min());
- assert(output()->zero_point() <= std::numeric_limits<uint8_t>::max());
- const auto pad_value = static_cast<uint8_t>(output()->zero_point());
- tflite::reference_ops::Pad(params, getTensorShape(input()), getTensorData<uint8_t>(input()),
- &pad_value, getTensorShape(output()),
- getTensorData<uint8_t>(output()));
- break;
- }
- case DataType::S8:
- {
- assert(output()->zero_point() >= std::numeric_limits<int8_t>::min());
- assert(output()->zero_point() <= std::numeric_limits<int8_t>::max());
- const auto pad_value = static_cast<int8_t>(output()->zero_point());
- tflite::reference_ops::Pad(params, getTensorShape(input()), getTensorData<int8_t>(input()),
- &pad_value, getTensorShape(output()),
- getTensorData<int8_t>(output()));
- break;
- }
- default:
- assert(false && "Unsupported type.");
- }
+ execute_kernel_CirclePadCommon(cur_op, runtime_graph);
}
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Pad.h b/onert-micro/luci-interpreter/src/kernels/Pad.h
deleted file mode 100644
index f6a9cfca5..000000000
--- a/onert-micro/luci-interpreter/src/kernels/Pad.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_PAD_H
-#define LUCI_INTERPRETER_KERNELS_PAD_H
-
-#include "core/Kernel.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Pad : public Kernel
-{
-public:
- Pad(const Tensor *input, const Tensor *paddings, Tensor *output);
-
- const Tensor *input() const { return _inputs[0]; }
- const Tensor *paddings() const { return _inputs[1]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_PAD_H
diff --git a/onert-micro/luci-interpreter/src/kernels/Pad.test.cpp b/onert-micro/luci-interpreter/src/kernels/Pad.test.cpp
index 95a28b697..3c835cbc0 100644
--- a/onert-micro/luci-interpreter/src/kernels/Pad.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Pad.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,96 +14,73 @@
* limitations under the License.
*/
-#include "kernels/Pad.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/pad/FloatPadKernel.h"
+#include "luci_interpreter/test_models/pad/NegPadKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
using namespace testing;
-float GetTolerance(float min, float max) { return (max - min) / 255.0; }
+class PadTest : public ::testing::Test
+{
+ // Do nothing
+};
-TEST(Pad, Uint8)
+template <typename T> std::vector<T> checkPadKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- float kQuantizedTolerance = GetTolerance(-1.0, 1.0);
- std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(-1.0f, 1.0f);
- std::vector<float> input_data{-0.8, 0.2, 0.9, 0.7, 0.1, -0.3};
- std::vector<int32_t> paddings_data{0, 0, 0, 2, 1, 3, 0, 0};
- Tensor input_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 3, 1}, quant_param.first, quant_param.second, input_data, memory_manager.get());
- Tensor paddings_tensor =
- makeInputTensor<DataType::S32>({4, 2}, paddings_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.second);
-
- Pad kernel(&input_tensor, &paddings_tensor, &output_tensor);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- std::vector<float> ref_output_data{0, -0.8, 0.2, 0.9, 0, 0, 0, 0, 0.7, 0.1, -0.3, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- EXPECT_THAT(dequantizeTensorData(output_tensor),
- FloatArrayNear(ref_output_data, kQuantizedTolerance));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 4, 7, 1}));
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
+
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
+
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
+
+ runtime_module.execute();
+
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
+
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST(Pad, Int8)
+TEST_F(PadTest, Float_P)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- float kQuantizedTolerance = GetTolerance(-1.0, 1.0);
- std::pair<float, int32_t> quant_param = quantizationParams<int8_t>(-1.0f, 1.0f);
- std::vector<float> input_data{-0.2, 0.4, 0.5, -0.7, -0.1, -0.9, 0.7, 0.1, 0.2};
- std::vector<int32_t> paddings_data{0, 0, 1, 2, 2, 1, 0, 0};
- Tensor input_tensor = makeInputTensor<DataType::S8>(
- {1, 3, 3, 1}, quant_param.first, quant_param.second, input_data, memory_manager.get());
- Tensor paddings_tensor =
- makeInputTensor<DataType::S32>({4, 2}, paddings_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S8, quant_param.first, quant_param.second);
-
- Pad kernel(&input_tensor, &paddings_tensor, &output_tensor);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- std::vector<float> ref_output_data{0, 0, 0, 0, 0, 0, 0, 0, -0.2, 0.4, 0.5, 0,
- 0, 0, -0.7, -0.1, -0.9, 0, 0, 0, 0.7, 0.1, 0.2, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- EXPECT_THAT(dequantizeTensorData(output_tensor),
- FloatArrayNear(ref_output_data, kQuantizedTolerance));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 6, 6, 1}));
+ test_kernel::TestDataFloatPad test_data_kernel;
+ std::vector<float> output_data_vector = checkPadKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-TEST(Pad, Float)
+TEST_F(PadTest, Input_output_type_mismatch_NEG)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- std::vector<float> input_data{1, 2, 3, 4, 5, 6};
- std::vector<int32_t> paddings_data{1, 0, 0, 2, 0, 3, 0, 0};
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>({1, 2, 3, 1}, input_data, memory_manager.get());
- Tensor paddings_tensor =
- makeInputTensor<DataType::S32>({4, 2}, paddings_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- Pad kernel(&input_tensor, &paddings_tensor, &output_tensor);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- std::vector<float> ref_output_data{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 4, 5,
- 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- std::initializer_list<int32_t> ref_output_shape{2, 4, 6, 1};
- EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+ test_kernel::NegTestDataInputOutputTypeMismatchPadKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/PadCommon.cpp b/onert-micro/luci-interpreter/src/kernels/PadCommon.cpp
new file mode 100644
index 000000000..92cd11758
--- /dev/null
+++ b/onert-micro/luci-interpreter/src/kernels/PadCommon.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Builders.h"
+#include "kernels/Utils.h"
+
+#include "PadCommon.h"
+#include "PALPad.h"
+
+namespace luci_interpreter
+{
+void configure_kernel_CirclePadCommon(const circle::Operator *cur_op,
+ BaseRuntimeGraph *runtime_graph)
+{
+ const auto num_inputs = cur_op->inputs()->size();
+
+ const auto input1_index = cur_op->inputs()->operator[](0);
+ const auto input2_index = cur_op->inputs()->operator[](1);
+ const auto input3_index = num_inputs == 3 ? cur_op->inputs()->operator[](2) : -1;
+ const auto output_index = cur_op->outputs()->operator[](0);
+
+ assert(input1_index != -1);
+ assert(input2_index != -1);
+ assert(input3_index != -1 or num_inputs == 2);
+ assert(output_index != -1);
+
+ const auto input1_tensor = runtime_graph->getCircleTensorByIndex(input1_index);
+ const auto input2_tensor = runtime_graph->getCircleTensorByIndex(input2_index);
+ const auto input3_tensor =
+ num_inputs == 3 ? runtime_graph->getCircleTensorByIndex(input3_index) : nullptr;
+ const auto output_tensor = runtime_graph->getCircleTensorByIndex(output_index);
+
+ assert(input1_tensor != nullptr);
+ assert(input2_tensor != nullptr);
+ assert(input3_tensor != nullptr or num_inputs == 2);
+ assert(output_tensor != nullptr);
+
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(input2_tensor) == DataType::S32);
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(input1_tensor) ==
+ Tensor::element_type(output_tensor));
+ if (input3_tensor != nullptr)
+ {
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(input3_tensor) ==
+ Tensor::element_type(input1_tensor));
+ // Value is scalar
+ LUCI_INTERPRETER_CHECK(Tensor::num_elements(input3_tensor) == 1);
+ }
+
+ // Check shapes
+ const int32_t *paddings_data =
+ kernels::getTensorData<int32_t>(runtime_graph->getConstDataByTensor(input2_tensor));
+ for (int i = 0; i < Tensor::num_dims(output_tensor); i++)
+ {
+ int output_dim = Tensor::dim(output_tensor, i);
+ int expected_dim =
+ Tensor::dim(input1_tensor, i) + paddings_data[i * 2] + paddings_data[i * 2 + 1];
+ LUCI_INTERPRETER_CHECK(output_dim == expected_dim);
+ }
+}
+
+void execute_kernel_CirclePadCommon(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+ const auto num_inputs = cur_op->inputs()->size();
+
+ const auto input1_index = cur_op->inputs()->operator[](0);
+ const auto input2_index = cur_op->inputs()->operator[](1);
+ const auto input3_index = num_inputs == 3 ? cur_op->inputs()->operator[](2) : -1;
+ const auto output_index = cur_op->outputs()->operator[](0);
+
+ assert(input1_index != -1);
+ assert(input2_index != -1);
+ assert(input3_index != -1 or num_inputs == 2);
+ assert(output_index != -1);
+
+ const auto input1_tensor = runtime_graph->getCircleTensorByIndex(input1_index);
+ const auto input2_tensor = runtime_graph->getCircleTensorByIndex(input2_index);
+ const auto input3_tensor =
+ num_inputs == 3 ? runtime_graph->getCircleTensorByIndex(input3_index) : nullptr;
+ const auto output_tensor = runtime_graph->getCircleTensorByIndex(output_index);
+
+ assert(input1_tensor != nullptr);
+ assert(input2_tensor != nullptr);
+ assert(input3_tensor != nullptr or num_inputs == 2);
+ assert(output_tensor != nullptr);
+
+ luci_interpreter_pal::PadParams pad_params;
+ const int num_input_dimensions = Tensor::num_dims(input1_tensor);
+ pad_params.left_padding_count = num_input_dimensions;
+ pad_params.right_padding_count = num_input_dimensions;
+
+ const int32_t *paddings_data =
+ kernels::getTensorData<int32_t>(runtime_graph->getConstDataByTensor(input2_tensor));
+ for (int idx = num_input_dimensions - 1; idx >= 0; --idx)
+ {
+ pad_params.left_padding[idx] = paddings_data[idx * 2];
+ pad_params.right_padding[idx] = paddings_data[idx * 2 + 1];
+ }
+
+ auto *input1_data = runtime_graph->getDataByTensor(input1_tensor);
+ if (input1_data == nullptr)
+ input1_data = runtime_graph->getConstDataByTensor(input1_tensor);
+ assert(input1_data);
+
+ auto *input2_data = runtime_graph->getConstDataByTensor(input2_tensor);
+ assert(input2_data);
+
+ auto *output_data = runtime_graph->getDataByTensor(output_tensor);
+ assert(output_data);
+
+ switch (Tensor::element_type(input1_tensor))
+ {
+#ifndef DIS_FLOAT
+ case DataType::FLOAT32:
+ {
+ float pad_value =
+ input3_tensor == nullptr
+ ? 0.f
+ : *kernels::getTensorData<float>(runtime_graph->getConstDataByTensor(input3_tensor));
+ luci_interpreter_pal::Pad(pad_params, kernels::getTensorShape(input1_tensor),
+ kernels::getTensorData<float>(input1_data), &pad_value,
+ kernels::getTensorShape(output_tensor),
+ kernels::getTensorData<float>(output_data));
+ }
+ break;
+#endif // DIS_FLOAT
+ default:
+ assert(false && "Unsupported type");
+ }
+}
+
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Neg.cpp b/onert-micro/luci-interpreter/src/kernels/PadCommon.h
index a898f41f5..d8fa4bed3 100644
--- a/onert-micro/luci-interpreter/src/loader/nodes/Neg.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/PadCommon.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,22 +14,20 @@
* limitations under the License.
*/
-#include "Builders.h"
+#ifndef LUCI_INTERPRETER_KERNELS_PAD_COMMON_H
+#define LUCI_INTERPRETER_KERNELS_PAD_COMMON_H
-#include "kernels/Neg.h"
+#include "Builders.h"
+#include "kernels/Utils.h"
namespace luci_interpreter
{
+void configure_kernel_CirclePadCommon(const circle::Operator *cur_op,
+ BaseRuntimeGraph *runtime_graph);
-std::unique_ptr<Kernel> build_kernel_CircleNeg(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 1);
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::Neg>(input, output);
-}
+void execute_kernel_CirclePadCommon(const circle::Operator *cur_op,
+ BaseRuntimeGraph *runtime_graph);
} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_KERNELS_PAD_COMMON_H
diff --git a/onert-micro/luci-interpreter/src/kernels/PadV2.cpp b/onert-micro/luci-interpreter/src/kernels/PadV2.cpp
index 2b759a829..7e0f61b8d 100644
--- a/onert-micro/luci-interpreter/src/kernels/PadV2.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/PadV2.cpp
@@ -1,6 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,95 +14,19 @@
* limitations under the License.
*/
-#include "kernels/PadV2.h"
-
-#include "kernels/Utils.h"
-
-#include <tensorflow/lite/kernels/internal/reference/pad.h>
-
-#include <limits>
+#include "Builders.h"
+#include "PadCommon.h"
namespace luci_interpreter
{
-namespace kernels
-{
-
-PadV2::PadV2(const Tensor *input, const Tensor *paddings, const Tensor *constant_values,
- Tensor *output)
- : Kernel({input, paddings, constant_values}, {output})
-{
-}
-
-void PadV2::configure()
+void configure_kernel_CirclePadV2(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- const Shape &input_shape = input()->shape();
- const int num_dims = input_shape.num_dims();
-
- if (num_dims > 4)
- assert(false && "Unsupported number of dimensions.");
-
- assert(output()->element_type() == input()->element_type());
- assert(paddings()->element_type() == DataType::S32);
- assert(constant_values()->element_type() == output()->element_type());
- // Paddings shape should be [N, 2].
- assert(paddings()->shape().num_dims() == 2);
- assert(paddings()->shape().dim(0) == num_dims);
- assert(paddings()->shape().dim(1) == 2);
- // Constant values elements number should be 1.
- assert(constant_values()->shape().num_elements() == 1);
-
- Shape output_shape(num_dims);
- const auto *paddings_data = getTensorData<int32_t>(paddings());
- for (int i = 0; i < num_dims; ++i)
- {
- const int32_t padding_before = paddings_data[i * 2];
- const int32_t padding_after = paddings_data[i * 2 + 1];
- assert(padding_before >= 0 && padding_after >= 0);
- output_shape.dim(i) = input_shape.dim(i) + padding_before + padding_after;
- }
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(output_shape);
+ configure_kernel_CirclePadCommon(cur_op, runtime_graph);
}
-void PadV2::execute() const
+void execute_kernel_CirclePadV2(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- const int num_dims = input()->shape().num_dims();
-
- tflite::PadParams params{};
- params.left_padding_count = num_dims;
- params.right_padding_count = num_dims;
-
- const auto *paddings_data = getTensorData<int32_t>(paddings());
- for (int i = num_dims - 1; i >= 0; --i)
- {
- params.left_padding[i] = paddings_data[i * 2];
- params.right_padding[i] = paddings_data[i * 2 + 1];
- }
-
- switch (input()->element_type())
- {
- case DataType::FLOAT32:
- {
- const auto pad_value = getTensorData<float>(constant_values())[0];
- tflite::reference_ops::Pad(params, getTensorShape(input()), getTensorData<float>(input()),
- &pad_value, getTensorShape(output()),
- getTensorData<float>(output()));
- break;
- }
- case DataType::U8:
- {
- assert(output()->zero_point() >= std::numeric_limits<uint8_t>::min());
- assert(output()->zero_point() <= std::numeric_limits<uint8_t>::max());
- const auto pad_value = getTensorData<uint8_t>(constant_values())[0];
- tflite::reference_ops::Pad(params, getTensorShape(input()), getTensorData<uint8_t>(input()),
- &pad_value, getTensorShape(output()),
- getTensorData<uint8_t>(output()));
- break;
- }
- default:
- assert(false && "Unsupported type.");
- }
+ execute_kernel_CirclePadCommon(cur_op, runtime_graph);
}
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/PadV2.h b/onert-micro/luci-interpreter/src/kernels/PadV2.h
deleted file mode 100644
index 546dba998..000000000
--- a/onert-micro/luci-interpreter/src/kernels/PadV2.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_PAD_V2_H
-#define LUCI_INTERPRETER_KERNELS_PAD_V2_H
-
-#include "core/Kernel.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class PadV2 : public Kernel
-{
-public:
- PadV2(const Tensor *input, const Tensor *paddings, const Tensor *constant_values, Tensor *output);
-
- const Tensor *input() const { return _inputs[0]; }
- const Tensor *paddings() const { return _inputs[1]; }
- const Tensor *constant_values() const { return _inputs[2]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_PAD_V2_H
diff --git a/onert-micro/luci-interpreter/src/kernels/PadV2.test.cpp b/onert-micro/luci-interpreter/src/kernels/PadV2.test.cpp
index 9094a22eb..8be5b0252 100644
--- a/onert-micro/luci-interpreter/src/kernels/PadV2.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/PadV2.test.cpp
@@ -1,6 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,77 +14,73 @@
* limitations under the License.
*/
-#include "kernels/PadV2.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/pad_v2/FloatPadV2Kernel.h"
+#include "luci_interpreter/test_models/pad_v2/NegPadV2Kernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
using namespace testing;
-float GetTolerance(float min, float max) { return (max - min) / 255.0; }
+class PadV2Test : public ::testing::Test
+{
+ // Do nothing
+};
-TEST(PadV2, Uint8)
+template <typename T> std::vector<T> checkPadV2Kernel(test_kernel::TestDataBase<T> *test_data_base)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- float kQuantizedTolerance = GetTolerance(-1.0, 1.0);
- std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(-1.0f, 1.0f);
- std::vector<float> input_data{-0.8, 0.2, 0.9, 0.7, 0.1, -0.3};
- std::vector<int32_t> paddings_data{0, 0, 0, 2, 1, 3, 0, 0};
- std::vector<float> constant_values_data{0.5};
- Tensor input_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 3, 1}, quant_param.first, quant_param.second, input_data, memory_manager.get());
- Tensor paddings_tensor =
- makeInputTensor<DataType::S32>({4, 2}, paddings_data, memory_manager.get());
- Tensor constant_values = makeInputTensor<DataType::U8>(
- {1}, quant_param.first, quant_param.second, constant_values_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.second);
-
- PadV2 kernel(&input_tensor, &paddings_tensor, &constant_values, &output_tensor);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- std::vector<float> ref_output_data = {
- 0.5, -0.8, 0.2, 0.9, 0.5, 0.5, 0.5, 0.5, 0.7, 0.1, -0.3, 0.5, 0.5, 0.5, //
- 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}; //
- EXPECT_THAT(dequantizeTensorData(output_tensor),
- FloatArrayNear(ref_output_data, kQuantizedTolerance));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 4, 7, 1}));
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
+
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
+
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
+
+ runtime_module.execute();
+
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
+
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
+}
+
+TEST_F(PadV2Test, Float_P)
+{
+ test_kernel::TestDataFloatPadV2 test_data_kernel;
+ std::vector<float> output_data_vector = checkPadV2Kernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-TEST(PadV2, Float)
+TEST_F(PadV2Test, Input_output_type_mismatch_NEG)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- std::vector<float> input_data{1, 2, 3, 4, 5, 6};
- std::vector<int32_t> paddings_data{1, 0, 0, 2, 0, 3, 0, 0};
- std::vector<float> constant_values_data{7};
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>({1, 2, 3, 1}, input_data, memory_manager.get());
- Tensor paddings_tensor =
- makeInputTensor<DataType::S32>({4, 2}, paddings_data, memory_manager.get());
- Tensor constant_values =
- makeInputTensor<DataType::FLOAT32>({1}, constant_values_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- PadV2 kernel(&input_tensor, &paddings_tensor, &constant_values, &output_tensor);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- std::vector<float> ref_output_data{7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 1, 2, 3, 7, 7, 7, 4, 5,
- 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};
- std::initializer_list<int32_t> ref_output_shape{2, 4, 6, 1};
- EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+ test_kernel::NegTestDataInputOutputTypeMismatchPadV2Kernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Pow.cpp b/onert-micro/luci-interpreter/src/kernels/Pow.cpp
index 521e80dde..6345bf324 100644
--- a/onert-micro/luci-interpreter/src/kernels/Pow.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Pow.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Pow.h b/onert-micro/luci-interpreter/src/kernels/Pow.h
index 1e7906ecc..8ff865e40 100644
--- a/onert-micro/luci-interpreter/src/kernels/Pow.h
+++ b/onert-micro/luci-interpreter/src/kernels/Pow.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Pow.test.cpp b/onert-micro/luci-interpreter/src/kernels/Pow.test.cpp
index d71248d90..0e858115d 100644
--- a/onert-micro/luci-interpreter/src/kernels/Pow.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Pow.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Quantize.cpp b/onert-micro/luci-interpreter/src/kernels/Quantize.cpp
index 6c832f7b1..9f622d077 100644
--- a/onert-micro/luci-interpreter/src/kernels/Quantize.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Quantize.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Quantize.h b/onert-micro/luci-interpreter/src/kernels/Quantize.h
index bbb951bfa..006c5366f 100644
--- a/onert-micro/luci-interpreter/src/kernels/Quantize.h
+++ b/onert-micro/luci-interpreter/src/kernels/Quantize.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/ReduceCommon.cpp b/onert-micro/luci-interpreter/src/kernels/ReduceCommon.cpp
new file mode 100644
index 000000000..c93329cd8
--- /dev/null
+++ b/onert-micro/luci-interpreter/src/kernels/ReduceCommon.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Builders.h"
+#include "kernels/Utils.h"
+#include "TISOKernel.h"
+
+#include "PALReduceCommon.h"
+
+#include <cassert>
+
+namespace luci_interpreter
+{
+namespace
+{
+
+template <typename T>
+void reduceProdGeneric(kernels::TISOData *tiso_data, const circle::Tensor *input,
+ const circle::Tensor *axis, const circle::Tensor *output, bool keep_dims)
+{
+ const int input_rank = Tensor::num_dims(input);
+ const int num_axis = Tensor::num_elements(axis);
+
+ auto const input_dims = wrap(input->shape());
+ const auto output_shape = kernels::getTensorShape(output);
+
+ luci_interpreter_pal::ReduceGeneric<T>(
+ kernels::getTensorData<T>(tiso_data->input1_data),
+ reinterpret_cast<const int *>(input_dims.data()), input_rank,
+ kernels::getTensorData<T>(tiso_data->output_data),
+ kernels::getTensorData<int>(tiso_data->input2_data), num_axis,
+ /*init_value=*/T(1), output_shape.flatSize(),
+ [](const T current, const T in) -> T { return in * current; });
+}
+
+} // namespace
+
+void configure_kernel_CircleReduceCommon(const circle::Operator *cur_op,
+ BaseRuntimeGraph *runtime_graph)
+{
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
+
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) == DataType::S32 or
+ Tensor::element_type(kernel.input1()) == DataType::FLOAT32 or
+ Tensor::element_type(kernel.input1()) == DataType::S64);
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input2()) == DataType::S32);
+}
+
+void execute_kernel_CircleReduceCommon(const circle::Operator *cur_op,
+ BaseRuntimeGraph *runtime_graph)
+{
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
+ kernels::TISOData tiso_data = kernel.readData();
+
+ const auto *input = kernel.input1();
+ const auto *axis = kernel.input2();
+ const auto *output = kernel.output();
+
+ const auto *options = cur_op->builtin_options_as_ReducerOptions();
+
+ switch (Tensor::element_type(kernel.input1()))
+ {
+#ifndef DIS_FLOAT
+ case DataType::FLOAT32:
+ reduceProdGeneric<float>(&tiso_data, input, axis, output, options->keep_dims());
+ break;
+#endif // DIS_FLOAT
+ case DataType::S32:
+ reduceProdGeneric<int32_t>(&tiso_data, input, axis, output, options->keep_dims());
+ break;
+ case DataType::S64:
+ reduceProdGeneric<int64_t>(&tiso_data, input, axis, output, options->keep_dims());
+ break;
+ default:
+ assert(false && "Unsupported type");
+ }
+}
+
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/ReduceCommon.test.cpp b/onert-micro/luci-interpreter/src/kernels/ReduceCommon.test.cpp
new file mode 100644
index 000000000..33574600d
--- /dev/null
+++ b/onert-micro/luci-interpreter/src/kernels/ReduceCommon.test.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/TestUtils.h"
+#include "luci_interpreter/test_models/reduce_common/ReduceProdKernel.h"
+#include "luci_interpreter/test_models/reduce_common/NegReduceProdKernel.h"
+
+#include "loader/ModuleLoader.h"
+
+namespace luci_interpreter
+{
+namespace
+{
+
+using namespace testing;
+
+class ReduceCommonTest : public ::testing::Test
+{
+ // Do nothing
+};
+
+template <typename T>
+std::vector<T> checkReduceCommonKernel(test_kernel::TestDataBase<T> *test_data_base)
+{
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
+
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
+
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
+
+ runtime_module.execute();
+
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
+
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
+}
+
+TEST_F(ReduceCommonTest, Reduce_Prod_Float_P)
+{
+ test_kernel::TestDataFloatReduceProd test_data_float_reduce_prod;
+ std::vector<float> output_data_vector = checkReduceCommonKernel(&test_data_float_reduce_prod);
+ EXPECT_THAT(output_data_vector,
+ kernels::testing::FloatArrayNear(
+ test_data_float_reduce_prod.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(ReduceCommonTest, Reduce_Prod_Int_P)
+{
+ test_kernel::TestDataIntReduceProd test_data_int_reduce_prod;
+ std::vector<int32_t> output_data_vector = checkReduceCommonKernel(&test_data_int_reduce_prod);
+ EXPECT_THAT(output_data_vector, test_data_int_reduce_prod.get_output_data_by_index(0));
+}
+
+TEST_F(ReduceCommonTest, Wrong_input_type_NEG)
+{
+ test_kernel::NegTestDataWrongInputTypeReduceProdKernel test_data_kernel;
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
+}
+
+TEST_F(ReduceCommonTest, Wrong_axis_type_NEG)
+{
+ test_kernel::NegTestDataWrongAxisTypeReduceProdKernel test_data_kernel;
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
+}
+
+} // namespace
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Relu.cpp b/onert-micro/luci-interpreter/src/kernels/Relu.cpp
index 74c2c0fbf..c38f33238 100644
--- a/onert-micro/luci-interpreter/src/kernels/Relu.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Relu.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,100 +14,63 @@
* limitations under the License.
*/
-#include "kernels/Relu.h"
+#include "Builders.h"
#include "kernels/Utils.h"
+#include "SISOKernel.h"
-#include "PALRelu.h"
+#include "PALReluCommon.h"
namespace luci_interpreter
{
-namespace kernels
+void configure_kernel_CircleRelu(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
+ kernels::SISOKernel kernel(cur_op, runtime_graph);
-Relu::Relu(const Tensor *input, Tensor *output) : Kernel({input}, {output}) {}
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input()) ==
+ Tensor::element_type(kernel.output()));
+ LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.input()) == Tensor::num_dims(kernel.output()));
+ LUCI_INTERPRETER_CHECK(Tensor::num_elements(kernel.input()) ==
+ Tensor::num_elements(kernel.output()));
+}
-void Relu::configure()
+void execute_kernel_CircleRelu(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
- if (input()->element_type() == DataType::S16)
- {
- LUCI_INTERPRETER_CHECK(input()->zero_point() == 0 && output()->zero_point() == 0);
- }
+ kernels::SISOKernel kernel(cur_op, runtime_graph);
- if (input()->element_type() == DataType::U8 || input()->element_type() == DataType::S16)
- {
- double multiplier = input()->scale() / output()->scale();
- quantizeMultiplier(multiplier, &_output_multiplier, &_output_shift);
- }
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(input()->shape());
-}
+ const auto *input_data = runtime_graph->getDataByTensor(kernel.input());
+ assert(input_data);
-void Relu::execute() const
-{
- switch (input()->element_type())
+ auto *output_data = runtime_graph->getDataByTensor(kernel.output());
+
+ bool is_inplace = runtime_graph->is_inplace_op(cur_op);
+
+ switch (Tensor::element_type(kernel.input()))
{
+#ifndef DIS_FLOAT
case DataType::FLOAT32:
- evalFloat();
- break;
- case DataType::U8:
- evalQuantized();
- break;
- case DataType::S16:
- evalQuantizedS16();
+ {
+ const float *input_data_float = kernels::getTensorData<float>(input_data);
+ float *output_data_float = kernels::getTensorData<float>(output_data);
+ if (is_inplace)
+ {
+ output_data_float = const_cast<float *>(input_data_float);
+ }
+
+ assert(output_data_float);
+ const int flat_size =
+ kernels::getTensorRuntimeShape(kernel.input(), runtime_graph).flatSize();
+
+ luci_interpreter_pal::ReLUCommon(flat_size, input_data_float, output_data_float, 0.0f, false);
break;
+ }
+#endif // DIS_FLOAT
default:
- assert(false && "Unsupported type.");
+ assert(false && "Unsupported type");
}
-}
-
-void Relu::evalFloat() const
-{
- const auto input_data = getTensorData<float>(input());
- const auto input_shape = getTensorShape(input());
- auto output_data = getTensorData<float>(output());
- auto output_shape = getTensorShape(output());
- luci_interpreter_pal::Relu(input_shape, input_data, output_shape, output_data);
-}
-
-void Relu::evalQuantized() const
-{
- tflite::ReluParams params;
- params.input_offset = input()->zero_point();
- params.output_offset = output()->zero_point();
- params.output_multiplier = _output_multiplier;
- params.output_shift = _output_shift;
-
- params.quantized_activation_min =
- std::max(static_cast<int32_t>(std::numeric_limits<uint8_t>::min()), params.output_offset);
- params.quantized_activation_max = static_cast<int32_t>(std::numeric_limits<uint8_t>::max());
-
- luci_interpreter_pal::ReluX(params, getTensorShape(input()), getTensorData<uint8_t>(input()),
- getTensorShape(output()), getTensorData<uint8_t>(output()));
-}
-
-void Relu::evalQuantizedS16() const
-{
- const auto *input_data = getTensorData<int16_t>(input());
- auto *output_data = getTensorData<int16_t>(output());
-
- constexpr int32_t output_min = 0;
- constexpr int32_t output_max = std::numeric_limits<int16_t>::max();
-
- const int32_t num_elements = input()->shape().num_elements();
-
- for (int32_t i = 0; i < num_elements; ++i)
- {
- const int32_t input_val = input_data[i];
- int32_t output_val =
- tflite::MultiplyByQuantizedMultiplier(input_val, _output_multiplier, _output_shift);
- output_val = std::max(output_val, output_min);
- output_val = std::min(output_val, output_max);
- output_data[i] = static_cast<int16_t>(output_val);
- }
+ if (is_inplace)
+ runtime_graph->makeInplaceOperation(kernel.input(), kernel.output());
}
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Relu.h b/onert-micro/luci-interpreter/src/kernels/Relu.h
deleted file mode 100644
index 7dae445f4..000000000
--- a/onert-micro/luci-interpreter/src/kernels/Relu.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_RELU_H
-#define LUCI_INTERPRETER_KERNELS_RELU_H
-
-#include "core/Kernel.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Relu : public Kernel
-{
-public:
- Relu(const Tensor *input, Tensor *output);
-
- const Tensor *input() const { return _inputs[0]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-
-private:
- void evalFloat() const;
- void evalQuantized() const;
- void evalQuantizedS16() const;
-
-private:
- int32_t _output_multiplier{0};
- int32_t _output_shift{0};
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_RELU_H
diff --git a/onert-micro/luci-interpreter/src/kernels/Relu.test.cpp b/onert-micro/luci-interpreter/src/kernels/Relu.test.cpp
index bd32e3cc9..b0cb220b9 100644
--- a/onert-micro/luci-interpreter/src/kernels/Relu.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Relu.test.cpp
@@ -15,154 +15,73 @@
* limitations under the License.
*/
-#include "kernels/Relu.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/relu/FloatReLUKernel.h"
+#include "luci_interpreter/test_models/relu/NegReLUKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
using namespace testing;
-class ReluTest : public ::testing::Test
+class ReLUTest : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-TEST_F(ReluTest, FloatSimple)
+template <typename T> std::vector<T> checkReLUKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- std::vector<float> input_data{
- 0.0f, 1.0f, 3.0f, // Row 1
- 1.0f, -1.0f, -2.0f, // Row 2
- };
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- std::vector<float> ref_output_data{
- 0.0f, 1.0f, 3.0f, // Row 1
- 1.0f, 0.0f, 0.0f, // Row 2
- };
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>({2, 3}, input_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- Relu kernel(&input_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<float>(output_tensor),
- ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({2, 3}));
-}
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
-TEST_F(ReluTest, Uint8Quantized)
-{
- std::vector<float> input_data{
- 0, -6, 2, 4, //
- 3, -2, 7, 1, //
- };
- // Choose min / max in such a way that there are exactly 256 units to avoid rounding errors.
- const float f_min = (-128.0 / 128.0) * 8;
- const float f_max = (127.0 / 128.0) * 8;
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
- std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(f_min, f_max);
- Tensor input_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, quant_param.first, quant_param.second, input_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.second);
+ runtime_module.execute();
- Relu kernel(&input_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 4, 1}));
- EXPECT_THAT(extractTensorData<uint8_t>(output_tensor),
- ::testing::ElementsAreArray({128, 128, 160, 192, 176, 128, 240, 144}));
- EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear({0, 0, 2, 4, 3, 0, 7, 1}));
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST_F(ReluTest, Uint8Requantized)
+TEST_F(ReLUTest, Float_P)
{
- std::vector<float> input_data{
- 0, -6, 2, 4, //
- 3, -2, 7, 1, //
- };
-
- // Choose min / max in such a way that there are exactly 256 units to avoid rounding errors.
- const float in_min = (-128.0 / 128.0) * 8;
- const float in_max = (127.0 / 128.0) * 8;
- const float out_min = (0.0 / 256.0) * 8;
- const float out_max = (255.0 / 256.0) * 8;
-
- std::pair<float, int32_t> quant_input = quantizationParams<uint8_t>(in_min, in_max);
- Tensor input_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, quant_input.first, quant_input.second, input_data, _memory_manager.get());
-
- std::pair<float, int32_t> quant_output = quantizationParams<uint8_t>(out_min, out_max);
- Tensor output_tensor = makeOutputTensor(DataType::U8, quant_output.first, quant_output.second);
-
- Relu kernel(&input_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 4, 1}));
- EXPECT_THAT(extractTensorData<uint8_t>(output_tensor),
- ::testing::ElementsAreArray({0, 0, 64, 128, 96, 0, 224, 32}));
- EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear({0, 0, 2, 4, 3, 0, 7, 1}));
+ test_kernel::TestDataFloatReLU test_data_kernel;
+ std::vector<float> output_data_vector = checkReLUKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+ test_data_kernel.get_output_data_by_index(0), 0.0001f));
}
-TEST_F(ReluTest, SInt16)
+TEST_F(ReLUTest, Input_output_type_mismatch_NEG)
{
- std::vector<float> input_data{
- 0, -6, 2, 4, //
- 3, -2, 7, 1, //
- };
- std::vector<float> ref_output_data{
- 0, 0, 2, 4, //
- 3, 0, 7, 1, //
- };
-
- Tensor input_tensor =
- makeInputTensor<DataType::S16>({1, 2, 4, 1}, 0.5, 0, input_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S16, 0.25, 0);
-
- Relu kernel(&input_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 4, 1}));
- EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
-}
-
-TEST_F(ReluTest, Input_Output_Type_NEG)
-{
- Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U8);
-
- Relu kernel(&input_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(ReluTest, Invalid_Input_Type_NEG)
-{
- Tensor input_tensor = makeInputTensor<DataType::S64>({1}, {1}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S64);
-
- Relu kernel(&input_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- EXPECT_ANY_THROW(kernel.execute());
+ test_kernel::NegTestDataInputOutputTypeMismatchReLUKernel test_data_kernel;
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Relu6.cpp b/onert-micro/luci-interpreter/src/kernels/Relu6.cpp
index 0449708f3..718622858 100644
--- a/onert-micro/luci-interpreter/src/kernels/Relu6.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Relu6.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,74 +14,63 @@
* limitations under the License.
*/
-#include "kernels/Relu6.h"
+#include "Builders.h"
#include "kernels/Utils.h"
+#include "SISOKernel.h"
-#include "PALRelu6.h"
+#include "PALReluCommon.h"
namespace luci_interpreter
{
-namespace kernels
+void configure_kernel_CircleRelu6(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
+ kernels::SISOKernel kernel(cur_op, runtime_graph);
-Relu6::Relu6(const Tensor *input, Tensor *output) : Kernel({input}, {output}) {}
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input()) ==
+ Tensor::element_type(kernel.output()));
+ LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.input()) == Tensor::num_dims(kernel.output()));
+ LUCI_INTERPRETER_CHECK(Tensor::num_elements(kernel.input()) ==
+ Tensor::num_elements(kernel.output()));
+}
-void Relu6::configure()
+void execute_kernel_CircleRelu6(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
+ kernels::SISOKernel kernel(cur_op, runtime_graph);
- if (input()->element_type() == DataType::U8)
- {
- double multiplier = input()->scale() / output()->scale();
- quantizeMultiplier(multiplier, &_output_multiplier, &_output_shift);
- }
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(input()->shape());
-}
+ const auto *input_data = runtime_graph->getDataByTensor(kernel.input());
+ assert(input_data);
-void Relu6::execute() const
-{
- switch (input()->element_type())
+ auto *output_data = runtime_graph->getDataByTensor(kernel.output());
+
+ bool is_inplace = runtime_graph->is_inplace_op(cur_op);
+
+ switch (Tensor::element_type(kernel.input()))
{
+#ifndef DIS_FLOAT
case DataType::FLOAT32:
- evalFloat();
- break;
- case DataType::U8:
- evalQuantized();
+ {
+ const float *input_data_float = kernels::getTensorData<float>(input_data);
+ float *output_data_float = kernels::getTensorData<float>(output_data);
+ if (is_inplace)
+ {
+ output_data_float = const_cast<float *>(input_data_float);
+ }
+
+ assert(output_data_float);
+ const int flat_size =
+ kernels::getTensorRuntimeShape(kernel.input(), runtime_graph).flatSize();
+
+ luci_interpreter_pal::ReLUCommon(flat_size, input_data_float, output_data_float, 0.0f, true);
break;
+ }
+#endif // DIS_FLOAT
default:
- assert(false && "Unsupported type.");
+ assert(false && "Unsupported type");
}
-}
-
-void Relu6::evalFloat() const
-{
- const auto input_data = getTensorData<float>(input());
- const auto input_shape = getTensorShape(input());
- auto output_data = getTensorData<float>(output());
- auto output_shape = getTensorShape(output());
-
- luci_interpreter_pal::Relu6(input_shape, input_data, output_shape, output_data);
-}
-
-void Relu6::evalQuantized() const
-{
- tflite::ReluParams params;
- params.input_offset = input()->zero_point();
- params.output_offset = output()->zero_point();
- params.output_multiplier = _output_multiplier;
- params.output_shift = _output_shift;
-
- params.quantized_activation_min =
- std::max(static_cast<int32_t>(std::numeric_limits<uint8_t>::min()), params.output_offset);
- params.quantized_activation_max =
- std::min(static_cast<int32_t>(std::numeric_limits<uint8_t>::max()),
- params.output_offset + static_cast<int32>(roundf(6.f / output()->scale())));
- luci_interpreter_pal::ReluX(params, getTensorShape(input()), getTensorData<uint8_t>(input()),
- getTensorShape(output()), getTensorData<uint8_t>(output()));
+ if (is_inplace)
+ runtime_graph->makeInplaceOperation(kernel.input(), kernel.output());
}
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Relu6.test.cpp b/onert-micro/luci-interpreter/src/kernels/Relu6.test.cpp
index af7b3f3db..1b784f0d3 100644
--- a/onert-micro/luci-interpreter/src/kernels/Relu6.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Relu6.test.cpp
@@ -15,135 +15,73 @@
* limitations under the License.
*/
-#include "kernels/Relu6.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/relu6/FloatReLU6Kernel.h"
+#include "luci_interpreter/test_models/relu6/NegReLU6Kernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
using namespace testing;
-class Relu6Test : public ::testing::Test
+class ReLU6Test : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-TEST_F(Relu6Test, FloatSimple)
-{
- std::vector<float> input_data{
- 0.0f, 1.0f, 3.0f, // Row 1
- 7.0f, -1.0f, -2.0f, // Row 2
- };
-
- std::vector<float> ref_output_data{
- 0.0f, 1.0f, 3.0f, // Row 1
- 6.0f, 0.0f, 0.0f, // Row 2
- };
-
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>({2, 3}, input_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- Relu6 kernel(&input_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<float>(output_tensor),
- ::testing::ElementsAreArray(ref_output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({2, 3}));
-}
-
-TEST_F(Relu6Test, Uint8Quantized)
+template <typename T> std::vector<T> checkReLU6Kernel(test_kernel::TestDataBase<T> *test_data_base)
{
- // Choose min / max in such a way that there are exactly 256 units to avoid rounding errors.
- const float f_min = (-128.0 / 128.0) * 10;
- const float f_max = (127.0 / 128.0) * 10;
- const float tolerance = (f_max - f_min) / 255.0;
-
- std::vector<float> input_data{
- 0, -6, 2, 8, //
- -2, 3, 7, 1, //
- };
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(f_min, f_max);
- Tensor input_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, quant_param.first, quant_param.second, input_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.second);
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- Relu6 kernel(&input_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 4, 1}));
- EXPECT_THAT(extractTensorData<uint8_t>(output_tensor),
- ::testing::ElementsAreArray({128, 128, 154, 205, 128, 166, 205, 141}));
- EXPECT_THAT(dequantizeTensorData(output_tensor),
- FloatArrayNear({0, 0, 2, 6, 0, 3, 6, 1}, tolerance));
-}
-
-TEST_F(Relu6Test, Uint8Requantized)
-{
- // Choose min / max in such a way that there are exactly 256 units to avoid rounding errors.
- const float in_min = (-128.0 / 128.0) * 10;
- const float in_max = (127.0 / 128.0) * 10;
- const float out_min = (0.0 / 256.0) * 0;
- const float out_max = (255.0 / 256.0) * 6;
- const float tolerance = (in_max - in_min) / 255.0;
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
- std::vector<float> input_data{
- 0, -6, 2, 8, //
- -2, 3, 7, 1, //
- };
+ runtime_module.execute();
- std::pair<float, int32_t> quant_input = quantizationParams<uint8_t>(in_min, in_max);
- Tensor input_tensor = makeInputTensor<DataType::U8>(
- {1, 2, 4, 1}, quant_input.first, quant_input.second, input_data, _memory_manager.get());
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
- std::pair<float, int32_t> quant_output = quantizationParams<uint8_t>(out_min, out_max);
- Tensor output_tensor = makeOutputTensor(DataType::U8, quant_output.first, quant_output.second);
-
- Relu6 kernel(&input_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 4, 1}));
- EXPECT_THAT(extractTensorData<uint8_t>(output_tensor),
- ::testing::ElementsAreArray({0, 0, 87, 255, 0, 127, 255, 43}));
- EXPECT_THAT(dequantizeTensorData(output_tensor),
- FloatArrayNear({0, 0, 2, 6, 0, 3, 6, 1}, tolerance));
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST_F(Relu6Test, Input_Output_Type_NEG)
+TEST_F(ReLU6Test, Float_P)
{
- Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U8);
-
- Relu6 kernel(&input_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::TestDataFloatReLU6 test_data_kernel;
+ std::vector<float> output_data_vector = checkReLU6Kernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+ test_data_kernel.get_output_data_by_index(0), 0.0001f));
}
-TEST_F(Relu6Test, Invalid_Input_Type_NEG)
+TEST_F(ReLU6Test, Input_output_type_mismatch_NEG)
{
- Tensor input_tensor = makeInputTensor<DataType::S64>({1}, {1}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S64);
-
- Relu6 kernel(&input_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- EXPECT_ANY_THROW(kernel.execute());
+ test_kernel::NegTestDataInputOutputTypeMismatchReLU6Kernel test_data_kernel;
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Reshape.cpp b/onert-micro/luci-interpreter/src/kernels/Reshape.cpp
index ba47df4ab..7fe3e5636 100644
--- a/onert-micro/luci-interpreter/src/kernels/Reshape.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Reshape.cpp
@@ -16,6 +16,7 @@
*/
#include "Builders.h"
+#include "Utils.h"
#include <cassert>
#include <cstring>
@@ -23,35 +24,75 @@
namespace luci_interpreter
{
-void configure_kernel_CircleReshape(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+void configure_kernel_CircleReshape(const circle::Operator *, BaseRuntimeGraph *)
{
// Do nothing
}
-void execute_kernel_CircleReshape(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph,
- bool is_inplace)
+// TODO: reduce code duplication with ExpandDims
+void execute_kernel_CircleReshape(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
const auto input_index = cur_op->inputs()->operator[](0);
+ const auto shape_index = cur_op->inputs()->operator[](1);
const auto output_index = cur_op->outputs()->operator[](0);
assert(input_index != -1);
+ assert(shape_index != -1);
assert(output_index != -1);
const auto input = runtime_graph->getCircleTensorByIndex(input_index);
+ const auto shape = runtime_graph->getCircleTensorByIndex(shape_index);
const auto output = runtime_graph->getCircleTensorByIndex(output_index);
-
+ bool is_inplace = runtime_graph->is_inplace_op(cur_op);
if (is_inplace)
{
runtime_graph->makeInplaceOperation(input, output);
return;
}
- const auto input_data = (runtime_graph->getDataByTensor(input));
- auto output_data = (runtime_graph->getDataByTensor(output));
+ const auto input_data = runtime_graph->getDataByTensor(input);
+ auto shape_data = runtime_graph->getConstDataByTensor(shape);
+ auto output_data = runtime_graph->getDataByTensor(output);
assert(input_data != nullptr);
assert(output_data != nullptr);
+#ifndef DIS_DYN_SHAPES
+ if (shape_data == nullptr)
+ {
+ shape_data = runtime_graph->getDataByTensor(shape);
+ assert(shape_data != nullptr);
+
+ assert(Tensor::element_type(shape) == DataType::S32);
+
+ const int32_t *shape_data_int = kernels::getTensorData<int32_t>(shape_data);
+ const auto num_elements = Tensor::num_elements(shape);
+
+ luci_interpreter::RuntimeShape dynamic_shape(num_elements);
+ int32_t data_size = 1;
+ for (int i = 0; i < num_elements; ++i)
+ {
+ dynamic_shape.setDim(i, shape_data_int[i]);
+ data_size *= shape_data_int[i];
+ }
+ data_size *= size(Tensor::element_type(output));
+
+ runtime_graph->addDynamicShapeTensor(output, std::move(dynamic_shape));
+
+ if (data_size == 0)
+ {
+ runtime_graph->resetTensorData(nullptr, output);
+ return;
+ }
+
+ auto new_output_data = new uint8_t[data_size];
+ output_data = new_output_data;
+ runtime_graph->resetTensorData(new_output_data, output);
+ }
+#else
+ assert(shape_data != nullptr);
+#endif // DIS_DYN_SHAPES
+
const size_t element_size = getDataTypeSize(Tensor::element_type(input));
const int32_t num_elements = Tensor::num_elements(input);
std::memcpy(output_data, input_data, num_elements * element_size);
diff --git a/onert-micro/luci-interpreter/src/kernels/Reshape.test.cpp b/onert-micro/luci-interpreter/src/kernels/Reshape.test.cpp
index 7a2a638f8..ac1acfb1d 100644
--- a/onert-micro/luci-interpreter/src/kernels/Reshape.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Reshape.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,15 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#if 0
-#include "kernels/Reshape.h"
+
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/reshape/ReshapeKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
@@ -30,55 +28,52 @@ using namespace testing;
class ReshapeTest : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-// TODO Test types other than FLOAT32.
-
-TEST_F(ReshapeTest, Regular)
+template <typename T>
+std::vector<T> checkReshapeKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- Shape input_shape{1, 2, 2, 3};
- std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
- Shape shape_shape{2};
- std::vector<int32_t> shape_data{3, 4};
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
- Tensor shape_tensor =
- makeInputTensor<DataType::S32>(shape_shape, shape_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- Reshape kernel(&input_tensor, &shape_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
- EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(input_data));
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
+
+ runtime_module.execute();
+
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
+
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST_F(ReshapeTest, UnknownDimension)
+TEST_F(ReshapeTest, MainTest_P)
{
- Shape input_shape{2, 1, 2, 3};
- std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
- Shape shape_shape{3};
- std::vector<int32_t> shape_data{2, -1, 2};
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
- Tensor shape_tensor =
- makeInputTensor<DataType::S32>(shape_shape, shape_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- Reshape kernel(&input_tensor, &shape_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ test_kernel::TestDataReshapeKernel<float> test_data_kernel(false);
+ std::vector<float> output_data_vector = checkReshapeKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
- EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(input_data));
+TEST_F(ReshapeTest, MainTest_NEG)
+{
+ test_kernel::TestDataReshapeKernel<float> test_data_kernel(true);
+ EXPECT_DEATH(checkReshapeKernel(&test_data_kernel), "");
}
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
-#endif
diff --git a/onert-micro/luci-interpreter/src/kernels/ResizeBilinear.cpp b/onert-micro/luci-interpreter/src/kernels/ResizeBilinear.cpp
index 8d07ea70e..7ce3833b3 100644
--- a/onert-micro/luci-interpreter/src/kernels/ResizeBilinear.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/ResizeBilinear.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,61 +15,104 @@
* limitations under the License.
*/
-#include "kernels/ResizeBilinear.h"
-
+#include "Builders.h"
#include "kernels/Utils.h"
+#include "kernels/BinaryOpCommon.h"
+
#include "PALResizeBilinear.h"
namespace luci_interpreter
{
-namespace kernels
-{
-ResizeBilinear::ResizeBilinear(const Tensor *input, const Tensor *size, Tensor *output,
- const ResizeBilinearParams &params)
- : KernelWithParams<ResizeBilinearParams>({input, size}, {output}, params)
-{
-}
+/*
+ * ResizeBilinear Kernel:
+ * Description: resizing input Tensor by input constants using Bilinear Interpolation
+ * 2 Inputs: Input tensor ( Shape dimensions count = 4); Input constant (Shape dimensions count = 1,
+ * Num elements =2) Parameters: align_corners; half_pixel_centers;
+ *
+ * Example:
+ * Input(2, 2, 2, 1)
+ * |
+ * | Constant Input(2) [3,3] INT32
+ * | /
+ * ResizeBilinear
+ * |
+ * Output(2, 3, 3, 1) UINT8
+ */
-void ResizeBilinear::configure()
+void configure_kernel_CircleResizeBilinear(const circle::Operator *cur_op,
+ BaseRuntimeGraph *runtime_graph)
{
- LUCI_INTERPRETER_CHECK(input()->shape().num_dims() == 4);
- LUCI_INTERPRETER_CHECK(size()->shape().num_dims() == 1);
- LUCI_INTERPRETER_CHECK(size()->element_type() == DataType::S32);
- if (params().half_pixel_centers && params().align_corners)
+ // Check of the size of input. Should be 2
+ assert(cur_op->inputs()->size() == 2);
+ const auto input_index = cur_op->inputs()->operator[](0);
+ const auto size_index = cur_op->inputs()->operator[](1);
+ const auto output_index = cur_op->outputs()->operator[](0);
+
+ assert(input_index != -1);
+ assert(size_index != -1);
+ assert(output_index != -1);
+ // Get tensors
+ const auto input = runtime_graph->getCircleTensorByIndex(input_index);
+ const auto size = runtime_graph->getCircleTensorByIndex(size_index);
+ const auto output = runtime_graph->getCircleTensorByIndex(output_index);
+ // Check of the Input shape
+ assert(kernels::getTensorShape(input).dimensionsCount() == 4);
+ // Check of the Const input size shape
+ assert(kernels::getTensorShape(size).dimensionsCount() == 1);
+ assert(Tensor::element_type(size) == DataType::S32);
+ assert(kernels::getTensorShape(size).dims(0) == 2);
+
+ const auto *params = cur_op->builtin_options_as_ResizeBilinearOptions();
+ if (params->half_pixel_centers() && params->align_corners())
assert(false && "If half_pixel_centers is True, align_corners must be False.");
- LUCI_INTERPRETER_CHECK(size()->shape().dim(0) == 2);
- Shape output_shape(4);
- output_shape.dim(0) = input()->shape().dim(0);
- output_shape.dim(1) = getTensorData<int32_t>(size())[0];
- output_shape.dim(2) = getTensorData<int32_t>(size())[1];
- output_shape.dim(3) = input()->shape().dim(3);
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(output_shape);
}
-void ResizeBilinear::execute() const
+void execute_kernel_CircleResizeBilinear(const circle::Operator *cur_op,
+ BaseRuntimeGraph *runtime_graph)
{
- tflite::ResizeBilinearParams op_params{};
- op_params.align_corners = params().align_corners;
- op_params.half_pixel_centers = params().half_pixel_centers;
- switch (output()->element_type())
+ assert(cur_op->inputs()->size() == 2);
+ const auto input_index = cur_op->inputs()->operator[](0);
+ const auto size_index = cur_op->inputs()->operator[](1);
+ const auto output_index = cur_op->outputs()->operator[](0);
+
+ assert(input_index != -1);
+ assert(size_index != -1);
+ assert(output_index != -1);
+
+ const auto input = runtime_graph->getCircleTensorByIndex(input_index);
+ const auto size = runtime_graph->getCircleTensorByIndex(size_index);
+ const auto output = runtime_graph->getCircleTensorByIndex(output_index);
+
+ const uint8_t *input_data = runtime_graph->getDataByTensor(input);
+ const uint8_t *size_data = runtime_graph->getConstDataByTensor(size);
+ uint8_t *output_data = runtime_graph->getDataByTensor(output);
+
+ assert(input_data != nullptr);
+ assert(size_data != nullptr);
+ assert(output_data != nullptr);
+
+ // Get parameters
+ const auto *op_params = cur_op->builtin_options_as_ResizeBilinearOptions();
+
+ switch (Tensor::element_type(output))
{
case DataType::FLOAT32:
luci_interpreter_pal::ResizeBilinear(
- op_params, getTensorShape(input()), getTensorData<float>(input()), getTensorShape(size()),
- getTensorData<int32_t>(size()), getTensorShape(output()), getTensorData<float>(output()));
+ op_params, kernels::getTensorShape(input), kernels::getTensorData<float>(input_data),
+ kernels::getTensorShape(size), kernels::getTensorData<int32_t>(size_data),
+ kernels::getTensorShape(output), kernels::getTensorData<float>(output_data));
break;
case DataType::U8:
luci_interpreter_pal::ResizeBilinear(
- op_params, getTensorShape(input()), getTensorData<uint8_t>(input()), getTensorShape(size()),
- getTensorData<int32_t>(size()), getTensorShape(output()), getTensorData<uint8_t>(output()));
+ op_params, kernels::getTensorShape(input), kernels::getTensorData<uint8_t>(input_data),
+ kernels::getTensorShape(size), kernels::getTensorData<int32_t>(size_data),
+ kernels::getTensorShape(output), kernels::getTensorData<uint8_t>(output_data));
break;
default:
assert(false && "Unsupported type.");
}
}
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/ResizeBilinear.h b/onert-micro/luci-interpreter/src/kernels/ResizeBilinear.h
index 9159b3203..b7bdc2ab7 100644
--- a/onert-micro/luci-interpreter/src/kernels/ResizeBilinear.h
+++ b/onert-micro/luci-interpreter/src/kernels/ResizeBilinear.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/ResizeBilinear.test.cpp b/onert-micro/luci-interpreter/src/kernels/ResizeBilinear.test.cpp
index 933a1128c..d8ecae5a0 100644
--- a/onert-micro/luci-interpreter/src/kernels/ResizeBilinear.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/ResizeBilinear.test.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
* Copyright 2017 The TensorFlow Authors. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,9 +15,11 @@
* limitations under the License.
*/
-#include "kernels/ResizeBilinear.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "loader/ModuleLoader.h"
+#include "luci_interpreter/test_models/resize_bilinear/FloatResizeBilinearKernel.h"
+#include "luci_interpreter/test_models/resize_bilinear/U8ResizeBilinearKernel.h"
+#include "luci_interpreter/test_models/resize_bilinear/NegResizeBilinearKernel.h"
namespace luci_interpreter
{
@@ -28,226 +30,159 @@ namespace
using namespace testing;
+class ResizeBilinearTest : public ::testing::Test
+{
+ // Do nothing
+};
+
template <typename T>
-void Check(std::initializer_list<int32_t> input_shape, std::initializer_list<int32_t> size_shape,
- std::initializer_list<int32_t> output_shape, std::initializer_list<float> input_data,
- std::initializer_list<int32_t> size_data, std::initializer_list<float> output_data,
- bool align_corners, bool half_pixel_centers)
+std::vector<T> checkResizeBilinearKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
- Tensor size_tensor = makeInputTensor<DataType::S32>(size_shape, size_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- ResizeBilinearParams params{};
- params.align_corners = align_corners;
- params.half_pixel_centers = half_pixel_centers;
-
- ResizeBilinear kernel(&input_tensor, &size_tensor, &output_tensor, params);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
- EXPECT_THAT(extractTensorData<T>(output_tensor), FloatArrayNear(output_data));
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
+
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
+
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
+
+ runtime_module.execute();
+
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
+
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-template <>
-void Check<uint8_t>(std::initializer_list<int32_t> input_shape,
- std::initializer_list<int32_t> size_shape,
- std::initializer_list<int32_t> output_shape,
- std::initializer_list<float> input_data,
- std::initializer_list<int32_t> size_data,
- std::initializer_list<float> output_data, bool align_corners,
- bool half_pixel_centers)
+TEST_F(ResizeBilinearTest, Float_P)
{
- // On TFlite example use Uint8 value it self, so this means quant param scale 1.0f and zero
- // point 0.
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-
- Tensor input_tensor =
- makeInputTensor<DataType::U8>(input_shape, 1.0, 0, input_data, memory_manager.get());
- Tensor size_tensor = makeInputTensor<DataType::S32>(size_shape, size_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U8, 1.0, 0);
-
- ResizeBilinearParams params{};
- params.align_corners = align_corners;
- params.half_pixel_centers = half_pixel_centers;
-
- ResizeBilinear kernel(&input_tensor, &size_tensor, &output_tensor, params);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
- EXPECT_THAT(dequantizeTensorData(output_tensor),
- FloatArrayNear(output_data, output_tensor.scale()));
+ test_kernel::TestDataFloatResizeBilinear test_data_kernel(false);
+ std::vector<float> output_data_vector = checkResizeBilinearKernel(&test_data_kernel);
+
+ EXPECT_THAT(output_data_vector,
+ FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
}
-template <typename T> class ResizeBilinearTest : public ::testing::Test
+TEST_F(ResizeBilinearTest, HalfPixelCenter_Float_P)
{
-};
-using DataTypes = ::testing::Types<float, uint8_t>;
-TYPED_TEST_SUITE(ResizeBilinearTest, DataTypes);
+ test_kernel::TestDataFloatResizeBilinear test_data_kernel(true);
+ std::vector<float> output_data_vector = checkResizeBilinearKernel(&test_data_kernel);
+
+ EXPECT_THAT(output_data_vector,
+ FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(ResizeBilinearTest, Uint8_P)
+{
+ test_kernel::TestDataUint8ResizeBilinear test_data_kernel(false);
+ std::vector<uint8_t> output_data_vector = checkResizeBilinearKernel<uint8_t>(&test_data_kernel);
+
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
-TYPED_TEST(ResizeBilinearTest, SimpleTest)
+TEST_F(ResizeBilinearTest, HalfPixelCenter_Uint8_P)
{
- Check<TypeParam>({2, 2, 2, 1}, {2}, {2, 3, 3, 1},
- {
- 3, 6, //
- 9, 12, //
- 4, 10, //
- 10, 16 //
- },
- {3, 3},
- {
- 3, 5, 6, //
- 7, 9, 10, //
- 9, 11, 12, //
- 4, 8, 10, //
- 8, 12, 14, //
- 10, 14, 16, //
- },
- false, false);
- SUCCEED();
+ test_kernel::TestDataUint8ResizeBilinear test_data_kernel(true);
+ std::vector<uint8_t> output_data_vector = checkResizeBilinearKernel<uint8_t>(&test_data_kernel);
+
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-TEST(ResizeBilinearTest, HalfPixelCenterFloatTest)
+TEST_F(ResizeBilinearTest, InvalidInputShape_Float_NEG)
{
- Check<float>({2, 2, 2, 1}, {2}, {2, 3, 3, 1},
- {
- 1, 2, //
- 3, 4, //
- 1, 2, //
- 3, 4 //
- },
- {3, 3},
- {
- 1, 1.5, 2, //
- 2, 2.5, 3, //
- 3, 3.5, 4, //
- 1, 1.5, 2, //
- 2, 2.5, 3, //
- 3, 3.5, 4, //
- },
- false, true);
- SUCCEED();
+
+ test_kernel::NegTestDataInvalidInputShapeFloatResizeBilinearKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST(ResizeBilinearTest, HalfPixelCenterUint8Test)
+TEST_F(ResizeBilinearTest, InvalidParams_Float_NEG)
{
- Check<uint8_t>({2, 2, 2, 1}, {2}, {2, 3, 3, 1},
- {
- 3, 6, //
- 9, 12, //
- 4, 10, //
- 12, 16 //
- },
- {3, 3},
- {
- 2, 4, 6, //
- 6, 7, 9, //
- 9, 10, 12, //
- 4, 7, 10, //
- 8, 10, 13, //
- 12, 14, 16, //
- },
- false, true);
- SUCCEED();
+
+ test_kernel::NegTestDataInvalidParamFloatResizeBilinearKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST(ResizeBilinearTest, InputShapeInvalid_NEG)
+TEST_F(ResizeBilinearTest, InvalidSizeShape_Float_NEG)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-
- Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({2, 2, 2},
- {
- 3, 6, //
- 9, 12, //
- 4, 10, //
- 10, 16 //
- },
- memory_manager.get());
- Tensor size_tensor = makeInputTensor<DataType::S32>({2}, {3, 3}, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- ResizeBilinearParams params{};
- params.align_corners = false;
- params.half_pixel_centers = false;
-
- ResizeBilinear kernel(&input_tensor, &size_tensor, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
+
+ test_kernel::NegTestDataInvalidSizeShapeDimensionsFloatResizeBilinearKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST(ResizeBilinearTest, SizeShapeInvalid_NEG)
+TEST_F(ResizeBilinearTest, InvalidInputShape_uint8_NEG)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-
- Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({2, 2, 2, 1},
- {
- 3, 6, //
- 9, 12, //
- 4, 10, //
- 10, 16 //
- },
- memory_manager.get());
- Tensor size_tensor = makeInputTensor<DataType::S32>({2, 1}, {3, 3}, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- ResizeBilinearParams params{};
- params.align_corners = false;
- params.half_pixel_centers = false;
-
- ResizeBilinear kernel(&input_tensor, &size_tensor, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
+
+ test_kernel::NegTestDataInvalidInputShapeUint8ResizeBilinearKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST(ResizeBilinearTest, SizeDimInvalid_NEG)
+TEST_F(ResizeBilinearTest, InvalidParams_uint8_NEG)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-
- Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({2, 2, 2, 1},
- {
- 3, 6, //
- 9, 12, //
- 4, 10, //
- 10, 16 //
- },
- memory_manager.get());
- Tensor size_tensor = makeInputTensor<DataType::S32>({3}, {3, 3, 1}, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- ResizeBilinearParams params{};
- params.align_corners = false;
- params.half_pixel_centers = false;
-
- ResizeBilinear kernel(&input_tensor, &size_tensor, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
+
+ test_kernel::NegTestDataInvalidParamUint8ResizeBilinearKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST(ResizeBilinearTest, InvalidParams_NEG)
+TEST_F(ResizeBilinearTest, InvalidSizeShape_uint8_NEG)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-
- Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({2, 2, 2, 1},
- {
- 3, 6, //
- 9, 12, //
- 4, 10, //
- 10, 16 //
- },
- memory_manager.get());
- Tensor size_tensor = makeInputTensor<DataType::S32>({2}, {3, 3}, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- ResizeBilinearParams params{};
- params.align_corners = true;
- params.half_pixel_centers = true;
-
- ResizeBilinear kernel(&input_tensor, &size_tensor, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
+
+ test_kernel::NegTestDataInvalidSizeShapeDimensionsUint8ResizeBilinearKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
} // namespace
diff --git a/onert-micro/luci-interpreter/src/kernels/ResizeNearestNeighbor.h b/onert-micro/luci-interpreter/src/kernels/ResizeNearestNeighbor.h
index d989490e9..137d031cf 100644
--- a/onert-micro/luci-interpreter/src/kernels/ResizeNearestNeighbor.h
+++ b/onert-micro/luci-interpreter/src/kernels/ResizeNearestNeighbor.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/ReverseV2.cpp b/onert-micro/luci-interpreter/src/kernels/ReverseV2.cpp
index 44a7faeba..76eadbdc8 100644
--- a/onert-micro/luci-interpreter/src/kernels/ReverseV2.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/ReverseV2.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/ReverseV2.h b/onert-micro/luci-interpreter/src/kernels/ReverseV2.h
index 096507536..51211c703 100644
--- a/onert-micro/luci-interpreter/src/kernels/ReverseV2.h
+++ b/onert-micro/luci-interpreter/src/kernels/ReverseV2.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Rsqrt.cpp b/onert-micro/luci-interpreter/src/kernels/Rsqrt.cpp
index 2788b679b..c45c3e4ca 100644
--- a/onert-micro/luci-interpreter/src/kernels/Rsqrt.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Rsqrt.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Rsqrt.h b/onert-micro/luci-interpreter/src/kernels/Rsqrt.h
index c64aecdee..adc5bcfa2 100644
--- a/onert-micro/luci-interpreter/src/kernels/Rsqrt.h
+++ b/onert-micro/luci-interpreter/src/kernels/Rsqrt.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Rsqrt.test.cpp b/onert-micro/luci-interpreter/src/kernels/Rsqrt.test.cpp
index 5567edb46..3c6494232 100644
--- a/onert-micro/luci-interpreter/src/kernels/Rsqrt.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Rsqrt.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/SISOKernel.h b/onert-micro/luci-interpreter/src/kernels/SISOKernel.h
new file mode 100644
index 000000000..98e352ab6
--- /dev/null
+++ b/onert-micro/luci-interpreter/src/kernels/SISOKernel.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_KERNELS_SISO_KERNEL_H
+#define LUCI_INTERPRETER_KERNELS_SISO_KERNEL_H
+
+#include "Builders.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+// Single input single output kernel
+class SISOKernel
+{
+public:
+ SISOKernel(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+ {
+ const auto input_index = cur_op->inputs()->operator[](0);
+ const auto output_index = cur_op->outputs()->operator[](0);
+
+ assert(input_index != -1);
+ assert(output_index != -1);
+
+ _input_tensor = runtime_graph->getCircleTensorByIndex(input_index);
+ _output_tensor = runtime_graph->getCircleTensorByIndex(output_index);
+
+ assert(_input_tensor != nullptr);
+ assert(_output_tensor != nullptr);
+ }
+
+ const circle::Tensor *input() const { return _input_tensor; }
+ const circle::Tensor *output() const { return _output_tensor; }
+
+private:
+ const circle::Tensor *_input_tensor;
+ const circle::Tensor *_output_tensor;
+};
+
+} // namespace kernels
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_KERNELS_SISO_KERNEL_H
diff --git a/onert-micro/luci-interpreter/src/kernels/SVDF.h b/onert-micro/luci-interpreter/src/kernels/SVDF.h
index 5141f452e..335a6cd8f 100644
--- a/onert-micro/luci-interpreter/src/kernels/SVDF.h
+++ b/onert-micro/luci-interpreter/src/kernels/SVDF.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/SVDF.test.cpp b/onert-micro/luci-interpreter/src/kernels/SVDF.test.cpp
index fbeaf5df0..82bd9b009 100644
--- a/onert-micro/luci-interpreter/src/kernels/SVDF.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/SVDF.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Shape.cpp b/onert-micro/luci-interpreter/src/kernels/Shape.cpp
index 2f16ac884..31a0b62bc 100644
--- a/onert-micro/luci-interpreter/src/kernels/Shape.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Shape.cpp
@@ -1,6 +1,5 @@
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,57 +14,33 @@
* limitations under the License.
*/
-#include "kernels/Shape.h"
+#include "Builders.h"
+#include "SISOKernel.h"
#include "kernels/Utils.h"
namespace luci_interpreter
{
-namespace kernels
+void configure_kernel_CircleShape(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
-
-ShapeKernel::ShapeKernel(const Tensor *input, Tensor *output, const ShapeParams &params)
- : KernelWithParams<ShapeParams>({input}, {output}, params)
-{
-}
-
-void ShapeKernel::configure()
-{
- LUCI_INTERPRETER_CHECK(output()->element_type() == DataType::S32 or
- output()->element_type() == DataType::S64);
- const auto input_shape = input()->shape();
-
- Shape output_shape(1);
- output_shape.dim(0) = input_shape.num_dims();
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(output_shape);
+ kernels::SISOKernel kernel(cur_op, runtime_graph);
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.output()) == DataType::S32);
}
-void ShapeKernel::execute() const
+void execute_kernel_CircleShape(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- switch (params().out_type)
- {
- case DataType::S32:
- evalInt<int32_t>();
- break;
- case DataType::S64:
- evalInt<int64_t>();
- break;
- default:
- assert(false && "Unsupported type.");
- }
-}
+ kernels::SISOKernel kernel(cur_op, runtime_graph);
-template <typename T> void ShapeKernel::evalInt() const
-{
- const auto input_shape = input()->shape();
+ const circle::Tensor *input = kernel.input();
+ const circle::Tensor *output = kernel.output();
- auto output_data = getTensorData<T>(output());
+ assert(Tensor::element_type(output) == DataType::S32);
+ int32_t *output_data = kernels::getTensorData<int32_t>(runtime_graph->getDataByTensor(output));
- for (int i = 0; i < input_shape.num_dims(); ++i)
+ const int rank = Tensor::num_dims(input);
+ for (int i = 0; i < rank; ++i)
{
- output_data[i] = input_shape.dim(i);
+ output_data[i] = Tensor::dim(input, i);
}
}
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Shape.test.cpp b/onert-micro/luci-interpreter/src/kernels/Shape.test.cpp
index 19c585890..f20eb784a 100644
--- a/onert-micro/luci-interpreter/src/kernels/Shape.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Shape.test.cpp
@@ -1,6 +1,5 @@
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,14 +14,14 @@
* limitations under the License.
*/
-#include "kernels/Shape.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/shape/ShapeKernel.h"
+#include "luci_interpreter/test_models/shape/NegShapeKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
@@ -30,61 +29,58 @@ using namespace testing;
class ShapeTest : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-template <typename T> void runShapeKernel(loco::DataType dataType, IMemoryManager *memory_manager)
+template <typename T, typename U>
+std::vector<U> checkShapeKernel(test_kernel::TestDataBase<T, U> *test_data_base)
{
- Shape input_shape{1, 3, 1, 3, 5};
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- Tensor input_tensor = Tensor(loco::DataType::FLOAT32, input_shape, {}, "");
- Tensor output_tensor = makeOutputTensor(dataType);
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- ShapeParams params{};
- params.out_type = dataType;
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
- ShapeKernel kernel(&input_tensor, &output_tensor, params);
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ runtime_module.execute();
- std::vector<T> ref_output_data{1, 3, 1, 3, 5};
- EXPECT_THAT(extractTensorData<T>(output_tensor), ref_output_data);
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
- std::vector<int32_t> ref_output_shape{5};
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+ U *output_data = reinterpret_cast<U *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(U));
+ std::vector<U> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST_F(ShapeTest, OutTypeInt)
+TEST_F(ShapeTest, MainTest_P)
{
-
- // Run for int32_t output
- runShapeKernel<int32_t>(loco::DataType::S32, _memory_manager.get());
- // Run for int64_t output
- runShapeKernel<int64_t>(loco::DataType::S64, _memory_manager.get());
-
- SUCCEED();
+ test_kernel::TestDataShapeKernel<float, int32_t> test_data_shape_kernel;
+ std::vector<int32_t> output_data_vector = checkShapeKernel(&test_data_shape_kernel);
+ EXPECT_THAT(output_data_vector, test_data_shape_kernel.get_output_data_by_index(0));
}
-TEST_F(ShapeTest, Invalid_Output_Type_NEG)
+TEST_F(ShapeTest, Wrong_output_type_NEG)
{
- Shape input_shape{1, 3};
-
- Tensor input_tensor = Tensor(loco::DataType::FLOAT32, input_shape, {}, "");
- Tensor output_tensor = makeOutputTensor(loco::DataType::FLOAT32);
-
- ShapeParams params{};
- params.out_type = loco::DataType::FLOAT32;
-
- ShapeKernel kernel(&input_tensor, &output_tensor, params);
-
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::NegTestDataWrongOutputTypeShapeKernel test_data_kernel;
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Slice.cpp b/onert-micro/luci-interpreter/src/kernels/Slice.cpp
index 7ae24bbba..34e549820 100644
--- a/onert-micro/luci-interpreter/src/kernels/Slice.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Slice.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,140 +14,222 @@
* limitations under the License.
*/
-#include "kernels/Slice.h"
-#include "Utils.h"
-#include "PALSlice.h"
+#include "Builders.h"
+#include "kernels/Utils.h"
+#include "MISOKernel.h"
#include <cassert>
-#include <cstring>
namespace luci_interpreter
{
-namespace kernels
+namespace
{
-const int max_dim = 4;
+const int max_dim = 5;
-Slice::Slice(const Tensor *input, const Tensor *begin, const Tensor *size, Tensor *output)
- : Kernel({input, begin, size}, {output})
+struct SliceParams
{
-}
+ int8_t begin_count;
+ int32_t begin[5];
+ int8_t size_count;
+ int32_t size[5];
+};
template <typename T>
-Shape calculateOutputShape(const Tensor *input, const Tensor *begin, const Tensor *size)
+inline void slice(const luci_interpreter::SliceParams &op_params,
+ const luci_interpreter::RuntimeShape &input_shape, const T *input_data,
+ const luci_interpreter::RuntimeShape &output_shape, T *output_data)
{
- Shape output_shape = Shape(input->shape().num_dims());
- for (int idx = 0; idx < input->shape().num_dims(); idx++)
+ const luci_interpreter::RuntimeShape ext_shape =
+ luci_interpreter::RuntimeShape::extendedShape(5, input_shape);
+ const int begin_count = op_params.begin_count;
+ const int size_count = op_params.size_count;
+ // We front-pad the begin and size vectors.
+ int start[5];
+ int stop[5];
+ for (int i = 0; i < 5; ++i)
{
- T size_value = getTensorData<T>(size)[idx];
- if (size_value < 0)
- {
- if (size_value != -1)
- {
- assert(false && "Invalid size.");
- }
- size_value = input->shape().dim(idx) - getTensorData<T>(begin)[idx];
- }
- else
+ int padded_i = 5 - i;
+ start[i] = begin_count < padded_i ? 0 : op_params.begin[begin_count - padded_i];
+ stop[i] = (size_count < padded_i || op_params.size[size_count - padded_i] == -1)
+ ? ext_shape.dims(i)
+ : start[i] + op_params.size[size_count - padded_i];
+ }
+
+ for (int i0 = start[0]; i0 < stop[0]; ++i0)
+ {
+ for (int i1 = start[1]; i1 < stop[1]; ++i1)
{
- if (input->shape().dim(idx) < getTensorData<T>(begin)[idx] + size_value)
+ for (int i2 = start[2]; i2 < stop[2]; ++i2)
{
- assert(false && "Invalid begin and size.");
+ for (int i3 = start[3]; i3 < stop[3]; ++i3)
+ {
+ for (int i4 = start[4]; i4 < stop[4]; ++i4)
+ {
+ auto position =
+ (((i0 * ext_shape.dims(1) + i1) * ext_shape.dims(2) + i2) * ext_shape.dims(3) + i3) *
+ ext_shape.dims(4) +
+ i4;
+ *output_data++ = input_data[position];
+ }
+ }
}
}
- output_shape.dim(idx) = static_cast<int>(size_value);
}
- return output_shape;
}
template <typename T>
-void getBeginAndSizeVectors(int dimensions, const Tensor *begin, const Tensor *size,
- std::vector<int> *begins, std::vector<int> *sizes)
+void getBeginAndSizeVectors(int dimensions, const uint8_t *begin_data, const uint8_t *size_data,
+ int32_t *begins, int32_t *sizes)
{
- for (int idx = dimensions - 1; idx >= 0; --idx)
+ int offset = max_dim - dimensions;
+ for (int idx = 0; idx < dimensions; ++idx)
{
- begins->push_back(getTensorData<T>(begin)[idx]);
- sizes->push_back(getTensorData<T>(size)[idx]);
+ begins[offset + idx] = kernels::getTensorData<T>(begin_data)[idx];
+ sizes[offset + idx] = kernels::getTensorData<T>(size_data)[idx];
}
}
+} // namespace
-void Slice::configure()
+void configure_kernel_CircleSlice(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- assert(input()->element_type() == output()->element_type());
- assert(begin()->element_type() == DataType::S32 || begin()->element_type() == DataType::S64);
- assert(size()->element_type() == DataType::S32 || size()->element_type() == DataType::S64);
- assert(begin()->shape().num_dims() == 1);
- assert(size()->shape().num_dims() == 1);
- assert(input()->shape().num_dims() <= max_dim);
- // TODO: enable it only if kernel with dynamic shapes
- if (begin()->element_type() == DataType::S32)
+ kernels::MISOKernel kernel(cur_op, runtime_graph);
+
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+ Tensor::element_type(kernel.output()));
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input2()) == DataType::S32 ||
+ Tensor::element_type(kernel.input2()) == DataType::S64);
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input3()) == DataType::S32 ||
+ Tensor::element_type(kernel.input3()) == DataType::S64);
+ LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.input2()) == 1);
+ LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.input3()) == 1);
+ LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.input1()) <= max_dim);
+}
+
+void execute_kernel_CircleSlice(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+ kernels::MISOKernel kernel(cur_op, runtime_graph);
+
+ bool is_dynamic_shapes = false;
+
+ const circle::Tensor *input = kernel.input1();
+ const circle::Tensor *begin = kernel.input2();
+ const circle::Tensor *size_tensor = kernel.input3();
+ const circle::Tensor *output = kernel.output();
+
+ const auto *input_data = runtime_graph->getDataByTensor(input);
+ if (input_data == nullptr)
+ input_data = runtime_graph->getConstDataByTensor(input);
+ assert(input_data);
+
+ const auto *begin_data = runtime_graph->getDataByTensor(begin);
+ if (begin_data == nullptr)
{
- output()->resize(calculateOutputShape<int32_t>(input(), begin(), size()));
+ begin_data = runtime_graph->getConstDataByTensor(begin);
+ is_dynamic_shapes = true;
}
- else if (begin()->element_type() == DataType::S64)
+ assert(begin_data);
+
+ const auto *size_data = runtime_graph->getDataByTensor(size_tensor);
+ if (size_data == nullptr)
{
- output()->resize(calculateOutputShape<int64_t>(input(), begin(), size()));
+ size_data = runtime_graph->getConstDataByTensor(size_tensor);
+ is_dynamic_shapes = true;
}
- else
+ assert(size_data);
+
+ auto *output_data = runtime_graph->getDataByTensor(output);
+ assert(output_data);
+
+ SliceParams op_params{};
+ op_params.begin_count = max_dim;
+ op_params.size_count = max_dim;
+ for (int i = 0; i < max_dim; i++)
{
- assert(false && "Unsupported type.");
+ op_params.begin[i] = 0;
+ op_params.size[i] = 1;
}
-}
+ auto num_dim = Tensor::num_dims(input);
-void Slice::execute() const
-{
- std::vector<int> begins;
- begins.reserve(max_dim);
- std::vector<int> sizes;
- sizes.reserve(max_dim);
- if (begin()->element_type() == DataType::S32)
+ if (Tensor::element_type(begin) == DataType::S32)
{
- getBeginAndSizeVectors<int32_t>(input()->shape().num_dims(), begin(), size(), &begins, &sizes);
+ getBeginAndSizeVectors<int32_t>(num_dim, begin_data, size_data, op_params.begin,
+ op_params.size);
}
- else if (begin()->element_type() == DataType::S64)
+ else if (Tensor::element_type(begin) == DataType::S64)
{
- getBeginAndSizeVectors<int64_t>(input()->shape().num_dims(), begin(), size(), &begins, &sizes);
+ getBeginAndSizeVectors<int64_t>(num_dim, begin_data, size_data, op_params.begin,
+ op_params.size);
}
else
{
- assert(false && "Unsupported begin type.");
- }
- for (int i = input()->shape().num_dims(); i < max_dim; ++i)
- {
- begins.push_back(0);
- sizes.push_back(1);
+ assert(false && "Unsupported type");
}
- assert(begins.size() == 4);
- assert(sizes.size() == 4);
- tflite::SliceParams op_params{};
- op_params.begin_count = 4;
- op_params.size_count = 4;
- for (int i = 0; i < 4; i++)
+#ifndef DIS_DYN_SHAPES
+ if (is_dynamic_shapes)
{
- op_params.begin[i] = begins[3 - i];
- op_params.size[i] = sizes[3 - i];
+ int32_t data_size = 1;
+ luci_interpreter::RuntimeShape dynamic_shapes(max_dim - num_dim + 1);
+ int offset = max_dim - Tensor::num_dims(input);
+ for (int i = 0; i <= max_dim - num_dim; ++i)
+ {
+ if (i + offset > 4)
+ return;
+ auto cur_size = op_params.size[i + offset] != -1
+ ? op_params.size[i + offset]
+ : Tensor::dim(input, i) - op_params.begin[i + offset];
+ data_size *= cur_size;
+
+ dynamic_shapes.setDim(i, cur_size);
+ }
+ data_size *= size(Tensor::element_type(output));
+
+ runtime_graph->addDynamicShapeTensor(output, std::move(dynamic_shapes));
+
+ if (data_size == 0)
+ {
+ runtime_graph->resetTensorData(nullptr, output);
+ return;
+ }
+
+ auto new_output_data = new uint8_t[data_size];
+ output_data = new_output_data;
+ runtime_graph->resetTensorData(new_output_data, output);
}
- switch (input()->element_type())
+#else
+ assert(is_dynamic_shapes == false);
+#endif // DIS_DYN_SHAPES
+
+ switch (Tensor::element_type(input))
{
+#ifndef DIS_FLOAT
case DataType::FLOAT32:
- luci_interpreter_pal::Slice(op_params, getTensorShape(input()), getTensorData<float>(input()),
- getTensorShape(output()), getTensorData<float>(output()));
+ slice<float>(op_params, kernels::getTensorShape(input),
+ kernels::getTensorData<float>(input_data), kernels::getTensorShape(output),
+ kernels::getTensorData<float>(output_data));
break;
+#endif // DIS_FLOAT
+#ifndef DIS_QUANT
case DataType::U8:
- luci_interpreter_pal::Slice(op_params, getTensorShape(input()),
- getTensorData<uint8_t>(input()), getTensorShape(output()),
- getTensorData<uint8_t>(output()));
+ slice<uint8_t>(op_params, kernels::getTensorShape(input),
+ kernels::getTensorData<uint8_t>(input_data), kernels::getTensorShape(output),
+ kernels::getTensorData<uint8_t>(output_data));
break;
case DataType::S8:
- luci_interpreter_pal::Slice(op_params, getTensorShape(input()),
- getTensorData<int8_t>(input()), getTensorShape(output()),
- getTensorData<int8_t>(output()));
+ slice<int8_t>(op_params, kernels::getTensorShape(input),
+ kernels::getTensorData<int8_t>(input_data), kernels::getTensorShape(output),
+ kernels::getTensorData<int8_t>(output_data));
+ break;
+ case DataType::S16:
+ slice<int16_t>(op_params, kernels::getTensorShape(input),
+ kernels::getTensorData<int16_t>(input_data), kernels::getTensorShape(output),
+ kernels::getTensorData<int16_t>(output_data));
break;
+#endif // DIS_QUANT
default:
assert(false && "Unsupported input type.");
}
}
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Slice.h b/onert-micro/luci-interpreter/src/kernels/Slice.h
deleted file mode 100644
index 5b415629e..000000000
--- a/onert-micro/luci-interpreter/src/kernels/Slice.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_SLICE_H
-#define LUCI_INTERPRETER_KERNELS_SLICE_H
-
-#include "core/Kernel.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Slice : public Kernel
-{
-public:
- Slice(const Tensor *input, const Tensor *begin, const Tensor *size, Tensor *output);
-
- const Tensor *input() const { return _inputs[0]; }
- const Tensor *begin() const { return _inputs[1]; }
- const Tensor *size() const { return _inputs[2]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_SLICE_H
diff --git a/onert-micro/luci-interpreter/src/kernels/Slice.test.cpp b/onert-micro/luci-interpreter/src/kernels/Slice.test.cpp
index 857dd1787..0bd13d748 100644
--- a/onert-micro/luci-interpreter/src/kernels/Slice.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Slice.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,57 +14,126 @@
* limitations under the License.
*/
-#include "kernels/Slice.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/slice/FloatSliceKernel.h"
+#include "luci_interpreter/test_models/slice/QuantU8SliceKernel.h"
+#include "luci_interpreter/test_models/slice/QuantS16SliceKernel.h"
+#include "luci_interpreter/test_models/slice/NegSliceKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
using namespace testing;
-template <typename T> class SliceTest : public ::testing::Test
+class SliceTest : public ::testing::Test
{
+ // Do nothing
};
-using DataTypes = ::testing::Types<float, uint8_t, int8_t>;
-TYPED_TEST_SUITE(SliceTest, DataTypes);
+template <typename T> std::vector<T> checkSliceKernel(test_kernel::TestDataBase<T> *test_data_base)
+{
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
+
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
+
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
+
+ runtime_module.execute();
+
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
-TYPED_TEST(SliceTest, SimpleTest)
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
+}
+
+TEST_F(SliceTest, Float_P)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-
- std::vector<TypeParam> input_data{1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6};
- Shape input_shape{3, 2, 3, 1};
- std::vector<int32_t> begin_data{1, 0, 0, 0};
- Shape begin_shape{4};
- std::vector<int32_t> size_data{2, 1, -1, 1};
- Shape size_shape{4};
- std::vector<TypeParam> output_data{3, 3, 3, 5, 5, 5};
- std::vector<int32_t> output_shape{2, 1, 3, 1};
-
- Tensor input_tensor =
- makeInputTensor<getElementType<TypeParam>()>(input_shape, input_data, memory_manager.get());
- Tensor begin_tensor =
- makeInputTensor<DataType::S32>(begin_shape, begin_data, memory_manager.get());
- Tensor size_tensor = makeInputTensor<DataType::S32>(size_shape, size_data, memory_manager.get());
-
- Tensor output_tensor = makeOutputTensor(getElementType<TypeParam>());
-
- Slice kernel(&input_tensor, &begin_tensor, &size_tensor, &output_tensor);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<TypeParam>(output_tensor),
- ::testing::ElementsAreArray(output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
+ test_kernel::TestDataFloatSlice test_data_kernel;
+ std::vector<float> output_data_vector = checkSliceKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
+TEST_F(SliceTest, U8_P)
+{
+ test_kernel::TestDataU8Slice test_data_kernel;
+ std::vector<uint8_t> output_data_vector = checkSliceKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(SliceTest, INT16_P)
+{
+ test_kernel::TestDataS16Slice test_data_kernel;
+ std::vector<int16_t> output_data_vector = checkSliceKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(SliceTest, TypeMismatch_NEG)
+{
+ test_kernel::TestDataTypeMismatchSlice test_data_kernel;
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
+}
+
+TEST_F(SliceTest, WrongBeginType_NEG)
+{
+ test_kernel::TestDataWrongBeginTypeSlice test_data_kernel;
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
+}
+
+TEST_F(SliceTest, WrongSizeType_NEG)
+{
+ test_kernel::TestDataWrongSizeTypeSlice test_data_kernel;
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
+}
+
+TEST_F(SliceTest, WrongInputShape_NEG)
+{
+ test_kernel::TestDataWrongInputShapeSlice test_data_kernel;
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
+}
+
+// TODO: add S8 test
+
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Softmax.cpp b/onert-micro/luci-interpreter/src/kernels/Softmax.cpp
index cfc1dfc6f..4647cc94e 100644
--- a/onert-micro/luci-interpreter/src/kernels/Softmax.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Softmax.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,8 +16,8 @@
#include "Builders.h"
#include "kernels/Utils.h"
+#include "SISOKernel.h"
-#include <tensorflow/lite/kernels/internal/reference/softmax.h>
#include "PALSoftmax.h"
namespace luci_interpreter
@@ -34,97 +33,48 @@ void evalFloat(const circle::Tensor *input, const circle::Tensor *output,
const auto *input_data = runtime_graph->getDataByTensor(input);
auto *output_data = runtime_graph->getDataByTensor(output);
- tflite::SoftmaxParams op_params{};
- op_params.beta = options->beta();
-
- tflite::reference_ops::Softmax(
- op_params, kernels::getTensorShape(input), kernels::getTensorData<float>(input_data),
- kernels::getTensorShape(output), kernels::getTensorData<float>(output_data));
+ luci_interpreter_pal::Softmax(options->beta(), kernels::getTensorShape(input),
+ kernels::getTensorData<float>(input_data),
+ kernels::getTensorData<float>(output_data));
}
#endif // DIS_FLOAT
-#ifndef DIS_QUANT
-template <typename T>
-void evalQuantized(const circle::Tensor *input, const circle::Tensor *output,
- const circle::SoftmaxOptions *options, BaseRuntimeGraph *runtime_graph)
-{
- // TODO: Enable it
- assert(false && "Not impl yet");
-
- const auto *input_data = runtime_graph->getDataByTensor(input);
- auto *output_data = runtime_graph->getDataByTensor(output);
-
- tflite::SoftmaxParams op_params{};
-
- luci_interpreter_pal::InitializeParams(&op_params, Tensor::scale(input), options->beta());
- luci_interpreter_pal::Softmax(
- op_params, kernels::getTensorShape(input), kernels::getTensorData<T>(input_data),
- kernels::getTensorShape(output), kernels::getTensorData<T>(output_data));
-}
-#endif
-
} // namespace
void configure_kernel_CircleSoftmax(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- const auto input_index = cur_op->inputs()->operator[](0);
- const auto output_index = cur_op->outputs()->operator[](0);
-
- assert(input_index != -1);
- assert(output_index != -1);
-
- const auto input = runtime_graph->getCircleTensorByIndex(input_index);
- auto output = runtime_graph->getCircleTensorByIndex(output_index);
+ kernels::SISOKernel kernel(cur_op, runtime_graph);
- assert(input != nullptr);
- assert(output != nullptr);
-
- LUCI_INTERPRETER_CHECK(Tensor::element_type(input) == Tensor::element_type(output));
- LUCI_INTERPRETER_CHECK(Tensor::num_dims(input) >= 1);
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input()) ==
+ Tensor::element_type(kernel.output()));
+ LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.input()) >= 1);
#ifndef DIS_QUANT
- if (Tensor::element_type(input) == DataType::U8 || Tensor::element_type(input) == DataType::S8)
+ if (Tensor::element_type(kernel.input()) == DataType::U8 ||
+ Tensor::element_type(kernel.input()) == DataType::S8)
{
- LUCI_INTERPRETER_CHECK(Tensor::element_type(input) == DataType::S8 ||
- Tensor::zero_point(output) == 0);
- LUCI_INTERPRETER_CHECK(Tensor::element_type(input) == DataType::U8 ||
- Tensor::zero_point(output) == std::numeric_limits<int8_t>::min());
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input()) == DataType::S8 ||
+ Tensor::zero_point(kernel.output()) == 0);
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input()) == DataType::U8 ||
+ Tensor::zero_point(kernel.output()) ==
+ std::numeric_limits<int8_t>::min());
}
#endif
}
-void execute_kernel_CircleSoftmax(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph,
- bool)
+void execute_kernel_CircleSoftmax(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- const auto input_index = cur_op->inputs()->operator[](0);
- const auto output_index = cur_op->outputs()->operator[](0);
-
- assert(input_index != -1);
- assert(output_index != -1);
-
- const auto input = runtime_graph->getCircleTensorByIndex(input_index);
- auto output = runtime_graph->getCircleTensorByIndex(output_index);
-
- assert(input != nullptr);
- assert(output != nullptr);
+ kernels::SISOKernel kernel(cur_op, runtime_graph);
const auto *options = cur_op->builtin_options_as_SoftmaxOptions();
- switch (Tensor::element_type(input))
+ switch (Tensor::element_type(kernel.input()))
{
#ifndef DIS_FLOAT
case DataType::FLOAT32:
- evalFloat(input, output, options, runtime_graph);
+ evalFloat(kernel.input(), kernel.output(), options, runtime_graph);
break;
#endif // DIS_FLOAT
-#ifndef DIS_QUANT
- case DataType::S8:
- evalQuantized<int8_t>(input, output, options, runtime_graph);
- break;
- case DataType::U8:
- evalQuantized<uint8_t>(input, output, options, runtime_graph);
- break;
-#endif // DIS_QUANT
default:
assert(false && "Unsupported type.");
}
diff --git a/onert-micro/luci-interpreter/src/kernels/Softmax.test.cpp b/onert-micro/luci-interpreter/src/kernels/Softmax.test.cpp
index d9656e52b..f026e89c4 100644
--- a/onert-micro/luci-interpreter/src/kernels/Softmax.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Softmax.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/SpaceToBatchND.h b/onert-micro/luci-interpreter/src/kernels/SpaceToBatchND.h
index 12640ca0d..0893003bb 100644
--- a/onert-micro/luci-interpreter/src/kernels/SpaceToBatchND.h
+++ b/onert-micro/luci-interpreter/src/kernels/SpaceToBatchND.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/SpaceToBatchND.test.cpp b/onert-micro/luci-interpreter/src/kernels/SpaceToBatchND.test.cpp
index aaf4e4756..3a8b0a812 100644
--- a/onert-micro/luci-interpreter/src/kernels/SpaceToBatchND.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/SpaceToBatchND.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/SpaceToDepth.cpp b/onert-micro/luci-interpreter/src/kernels/SpaceToDepth.cpp
index 3fab4028a..06cc5faae 100644
--- a/onert-micro/luci-interpreter/src/kernels/SpaceToDepth.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/SpaceToDepth.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/SpaceToDepth.h b/onert-micro/luci-interpreter/src/kernels/SpaceToDepth.h
index b9d9c38e3..e66316b11 100644
--- a/onert-micro/luci-interpreter/src/kernels/SpaceToDepth.h
+++ b/onert-micro/luci-interpreter/src/kernels/SpaceToDepth.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/SpaceToDepth.test.cpp b/onert-micro/luci-interpreter/src/kernels/SpaceToDepth.test.cpp
index 724abd053..4af488618 100644
--- a/onert-micro/luci-interpreter/src/kernels/SpaceToDepth.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/SpaceToDepth.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Split.cpp b/onert-micro/luci-interpreter/src/kernels/Split.cpp
index 9737a0149..70513a5cf 100644
--- a/onert-micro/luci-interpreter/src/kernels/Split.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Split.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,68 +14,80 @@
* limitations under the License.
*/
-#include "Split.h"
-
+#include "Builders.h"
#include "Utils.h"
-
-#include "PALSplit.h"
+#include "Split.h"
namespace luci_interpreter
{
-namespace kernels
-{
-Split::Split(const Tensor *axis, const Tensor *input, std::vector<Tensor *> outputs)
- : Kernel({axis, input}, std::move(outputs))
+void configure_kernel_CircleSplit(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
-}
+ const auto input_index = cur_op->inputs()->operator[](0);
+ const auto axis_index = cur_op->inputs()->operator[](1);
-void Split::configure()
-{
- assert(axis()->shape().num_elements() == 1);
- _axis_value = getTensorData<int32_t>(axis())[0];
- if (_axis_value < 0)
- _axis_value += input()->shape().num_dims();
- assert(_axis_value >= 0 && _axis_value < input()->shape().num_dims());
-
- const int32_t input_size = input()->shape().dim(_axis_value);
- assert(input_size % _outputs.size() == 0);
- const int32_t slice_size = input_size / _outputs.size();
- // TODO: enable it only if kernel with dynamic shapes
- Shape output_shape = input()->shape();
- output_shape.dim(_axis_value) = slice_size;
- for (Tensor *output : _outputs)
- {
- output->resize(output_shape);
- }
+ LUCI_INTERPRETER_CHECK(input_index != -1);
+ LUCI_INTERPRETER_CHECK(axis_index != -1);
+
+ const auto input = runtime_graph->getCircleTensorByIndex(input_index);
+ const auto axis = runtime_graph->getCircleTensorByIndex(axis_index);
+
+ LUCI_INTERPRETER_CHECK(input != nullptr);
+ LUCI_INTERPRETER_CHECK(axis != nullptr);
}
-void Split::execute() const
+void execute_kernel_CircleSplit(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- tflite::SplitParams params{};
- params.num_split = _outputs.size();
- params.axis = _axis_value;
-
-#define TF_LITE_SPLIT(scalar) \
- { \
- VectorOfTensors<scalar, false> all_outputs(_outputs); \
- luci_interpreter_pal::Split(params, getTensorShape(input()), getTensorData<scalar>(input()), \
- all_outputs.shapes(), all_outputs.data()); \
- }
+ const auto input_index = cur_op->inputs()->operator[](1);
+ const auto axis_index = cur_op->inputs()->operator[](0);
+
+ assert(input_index != -1);
+ assert(axis_index != -1);
+
+ const auto input = runtime_graph->getCircleTensorByIndex(input_index);
+ const auto axis = runtime_graph->getCircleTensorByIndex(axis_index);
+
+ assert(input != nullptr);
+ assert(axis != nullptr);
+
+ const auto *axis_data = runtime_graph->getDataByTensor(axis);
+ if (axis_data == nullptr)
+ axis_data = runtime_graph->getConstDataByTensor(axis);
+
+ assert(axis_data);
+
+ int32_t axis_value = (kernels::getTensorData<int32_t>(axis_data))[0];
+ if (axis_value < 0)
+ axis_value += Tensor::num_dims(input);
+
+ assert(axis_value >= 0);
+ assert(axis_value < Tensor::num_dims(input));
- switch (input()->element_type())
+ switch (Tensor::element_type(input))
{
+#ifndef DIS_FLOAT
case DataType::FLOAT32:
- TF_LITE_SPLIT(float);
- break;
- case DataType::U8:
- TF_LITE_SPLIT(uint8_t);
- break;
+ {
+ return splitImpl<float>(cur_op, input, axis_value, runtime_graph);
+ }
+#endif // DIS_FLOAT
+#ifndef DIS_QUANT
+ case DataType::S8:
+ {
+ return splitImpl<int8_t>(cur_op, input, axis_value, runtime_graph);
+ }
+ case DataType::S16:
+ {
+ return splitImpl<int16_t>(cur_op, input, axis_value, runtime_graph);
+ }
+#endif // DIS_QUANT
+ case DataType::S32:
+ {
+ return splitImpl<int32_t>(cur_op, input, axis_value, runtime_graph);
+ }
default:
- assert(false && "Unsupported type.");
+ assert(false && "Unsupported type");
}
-#undef TF_LITE_SPLIT
}
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Split.h b/onert-micro/luci-interpreter/src/kernels/Split.h
index 1892a74a5..99ffae866 100644
--- a/onert-micro/luci-interpreter/src/kernels/Split.h
+++ b/onert-micro/luci-interpreter/src/kernels/Split.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,34 +14,68 @@
* limitations under the License.
*/
-#ifndef LUCI_INTERPRETER_KERNELS_SPLIT_H
-#define LUCI_INTERPRETER_KERNELS_SPLIT_H
+#ifndef LUCI_INTERPRETER_KERNELS_SPLIT_IMPL_H
+#define LUCI_INTERPRETER_KERNELS_SPLIT_IMPL_H
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
+#include "Builders.h"
+#include "Utils.h"
namespace luci_interpreter
{
-namespace kernels
-{
-class Split : public Kernel
+template <typename T>
+void splitImpl(const circle::Operator *cur_op, const circle::Tensor *input, int axis_value,
+ BaseRuntimeGraph *runtime_graph)
{
-public:
- Split(const Tensor *axis, const Tensor *input, std::vector<Tensor *> outputs);
+ const int output_count = cur_op->outputs()->size();
+
+ const auto output0_index = cur_op->outputs()->operator[](0);
+ assert(output0_index != -1);
+
+ const auto output0 = runtime_graph->getCircleTensorByIndex(output0_index);
+ assert(output0 != nullptr);
+
+ const int split_dimensions = Tensor::num_dims(input);
+
+ assert(axis_value < split_dimensions);
+ assert(Tensor::num_dims(output0) == split_dimensions);
+
+ int64_t outer_size = 1;
+ for (int i = 0; i < axis_value; ++i)
+ {
+ outer_size *= Tensor::dim(input, i);
+ }
+
+ int64_t base_inner_size = 1;
+ for (int i = axis_value + 1; i < split_dimensions; ++i)
+ {
+ base_inner_size *= Tensor::dim(input, i);
+ }
- const Tensor *axis() const { return _inputs[0]; }
- const Tensor *input() const { return _inputs[1]; }
- Tensor *output(int index) const { return _outputs[index]; }
+ const T *input_ptr = kernels::getTensorData<T>(runtime_graph->getDataByTensor(input));
+ assert(input_ptr != nullptr);
+ for (int k = 0; k < outer_size; ++k)
+ {
+ for (int i = 0; i < output_count; ++i)
+ {
+ const auto output_index = cur_op->outputs()->operator[](i);
+ assert(output_index != -1);
- void configure() override;
- void execute() const override;
+ const auto output = runtime_graph->getCircleTensorByIndex(output_index);
+ assert(output != nullptr);
-private:
- int32_t _axis_value{};
-};
+ T *output_data = kernels::getTensorData<T>(runtime_graph->getDataByTensor(output));
+ assert(output_data != nullptr);
+ const int copy_size = Tensor::dim(output, axis_value) * base_inner_size;
+ T *output_ptr = output_data + k * copy_size;
+ assert(output_ptr != nullptr);
+ for (int j = 0; j < copy_size; ++j)
+ output_ptr[j] = input_ptr[j];
+ input_ptr += copy_size;
+ }
+ }
+}
-} // namespace kernels
} // namespace luci_interpreter
-#endif // LUCI_INTERPRETER_KERNELS_SPLIT_H
+#endif // LUCI_INTERPRETER_KERNELS_SPLIT_IMPL_H
diff --git a/onert-micro/luci-interpreter/src/kernels/Split.test.cpp b/onert-micro/luci-interpreter/src/kernels/Split.test.cpp
index 283cd9aa9..c091903d1 100644
--- a/onert-micro/luci-interpreter/src/kernels/Split.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Split.test.cpp
@@ -15,115 +15,85 @@
* limitations under the License.
*/
-#include "kernels/Split.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/split/FloatSplitKernel.h"
+#include "luci_interpreter/test_models/split/IntSplitKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
using namespace testing;
+class SplitTest : public ::testing::Test
+{
+ // Do nothing
+};
+
template <typename T>
-void Check(int axis, int num_splits, std::initializer_list<int32_t> input_shape,
- std::initializer_list<int32_t> output_shape, std::initializer_list<T> input_data,
- std::vector<std::vector<T>> output_data)
+std::vector<std::vector<T>> checkSplitKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- constexpr DataType element_type = getElementType<T>();
- Tensor axis_tensor = makeInputTensor<DataType::S32>({}, {axis}, memory_manager.get());
- Tensor input_tensor =
- makeInputTensor<element_type>(input_shape, input_data, memory_manager.get());
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- std::vector<Tensor> output_tensors;
- output_tensors.reserve(num_splits);
- for (int i = 0; i < num_splits; ++i)
- {
- output_tensors.emplace_back(makeOutputTensor(element_type));
- }
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
- std::vector<Tensor *> output_tensor_ptrs(num_splits);
- for (int i = 0; i < num_splits; ++i)
+ // Set input data
{
- output_tensor_ptrs[i] = &output_tensors[i];
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
}
- Split kernel(&axis_tensor, &input_tensor, std::move(output_tensor_ptrs));
- kernel.configure();
- for (int i = 0; i < num_splits; ++i)
- {
- memory_manager->allocate_memory(output_tensors[i]);
- }
- kernel.execute();
+ runtime_module.execute();
+
+ assert(main_runtime_graph->getNumOfOutputTensors() == 2);
+
+ std::vector<std::vector<T>> result;
- for (int i = 0; i < num_splits; ++i)
+ for (int i = 0; i < 2; ++i)
{
- EXPECT_THAT(extractTensorData<T>(output_tensors[i]),
- ::testing::ElementsAreArray(output_data[i]));
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(i));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(i) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ result.push_back(output_data_vector);
}
+
+ return result;
}
-template <typename T> class SplitTest : public ::testing::Test
+TEST_F(SplitTest, Float_P)
{
-};
-
-using DataTypes = ::testing::Types<float, uint8_t>;
-TYPED_TEST_SUITE(SplitTest, DataTypes);
+ test_kernel::TestDataFloatSplit test_data_kernel;
+ const auto output_data_vector = checkSplitKernel(&test_data_kernel);
-TYPED_TEST(SplitTest, FourDimensional)
-{
- Check<TypeParam>(/*axis=*/0, /*num_splits=*/2, {2, 2, 2, 2}, {1, 2, 2, 2},
- {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
- {
- {1, 2, 3, 4, 5, 6, 7, 8}, //
- {9, 10, 11, 12, 13, 14, 15, 16}, //
- });
- Check<TypeParam>(
- /*axis=*/1, /*num_splits=*/2, {2, 2, 2, 2}, {2, 1, 2, 2},
- {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
- {
- {1, 2, 3, 4, 9, 10, 11, 12}, //
- {5, 6, 7, 8, 13, 14, 15, 16}, //
- });
- Check<TypeParam>(
- /*axis=*/2, /*num_splits=*/2, {2, 2, 2, 2}, {2, 2, 1, 2},
- {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
- {
- {1, 2, 5, 6, 9, 10, 13, 14}, //
- {3, 4, 7, 8, 11, 12, 15, 16}, //
- });
- Check<TypeParam>(
- /*axis=*/3, /*num_splits=*/2, {2, 2, 2, 2}, {2, 2, 2, 1},
- {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
- {
- {1, 3, 5, 7, 9, 11, 13, 15}, //
- {2, 4, 6, 8, 10, 12, 14, 16}, //
- });
+ for (int i = 0; i < 2; ++i)
+ {
+ EXPECT_THAT(output_data_vector[i], test_data_kernel.get_output_data_by_index(i));
+ }
}
-TYPED_TEST(SplitTest, OneDimensional)
+TEST_F(SplitTest, Int_P)
{
- Check<TypeParam>(
- /*axis=*/0, /*num_splits=*/8, {8}, {1}, {1, 2, 3, 4, 5, 6, 7, 8},
- {{1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}});
-}
+ test_kernel::TestDataIntSplit test_data_kernel;
+ const auto output_data_vector = checkSplitKernel(&test_data_kernel);
-TYPED_TEST(SplitTest, NegativeAxis)
-{
- Check<TypeParam>(
- /*axis=*/-4, /*num_splits=*/2, {2, 2, 2, 2}, {1, 2, 2, 2},
- {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
- {
- {1, 2, 3, 4, 5, 6, 7, 8}, //
- {9, 10, 11, 12, 13, 14, 15, 16},
- });
+ for (int i = 0; i < 2; ++i)
+ {
+ EXPECT_THAT(output_data_vector[i], test_data_kernel.get_output_data_by_index(i));
+ }
}
+// TODO: add negative tests?
+
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/SplitV.cpp b/onert-micro/luci-interpreter/src/kernels/SplitV.cpp
index f01cf10b7..b78a394e4 100644
--- a/onert-micro/luci-interpreter/src/kernels/SplitV.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/SplitV.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2023 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,99 +15,78 @@
* limitations under the License.
*/
-#include "SplitV.h"
-
+#include "Builders.h"
#include "Utils.h"
-
-#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
+#include "Split.h"
namespace luci_interpreter
{
-namespace kernels
-{
-SplitV::SplitV(const Tensor *input, const Tensor *size_splits, const Tensor *axis,
- std::vector<Tensor *> outputs)
- : Kernel({input, size_splits, axis}, std::move(outputs))
+void configure_kernel_CircleSplitV(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
+ const auto axis_index = cur_op->inputs()->operator[](2);
+ LUCI_INTERPRETER_CHECK(axis_index != -1);
+
+ const auto axis = runtime_graph->getCircleTensorByIndex(axis_index);
+ LUCI_INTERPRETER_CHECK(axis != nullptr);
+
+ // Dynamic output tensors are needed if axis tensor is not constant
+ // Now doesn't support dynamic shapes for SplitV
+ LUCI_INTERPRETER_CHECK(runtime_graph->getConstDataByTensor(axis) != nullptr);
}
-void SplitV::configure()
+void execute_kernel_CircleSplitV(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- assert(axis()->shape().num_elements() == 1);
- _axis_value = getTensorData<int32_t>(axis())[0];
- if (_axis_value < 0)
- _axis_value += input()->shape().num_dims();
- assert(_axis_value >= 0 && _axis_value < input()->shape().num_dims());
+ const auto input_index = cur_op->inputs()->operator[](0);
+ const auto axis_index = cur_op->inputs()->operator[](2);
+
+ assert(input_index != -1);
+ assert(axis_index != -1);
- auto num_split = static_cast<int32_t>(_outputs.size());
- auto sizes_data = getTensorData<int32_t>(size_splits());
+ const auto input = runtime_graph->getCircleTensorByIndex(input_index);
+ const auto axis = runtime_graph->getCircleTensorByIndex(axis_index);
- assert(size_splits()->shape().num_dims() == 1);
+ assert(input != nullptr);
+ assert(axis != nullptr);
- int32_t sum = 0;
- const auto num_dims_size_spits = size_splits()->shape().dim(0);
- int32_t count_neg_dim = 0;
+ const auto *axis_data = runtime_graph->getDataByTensor(axis);
+ if (axis_data == nullptr)
+ axis_data = runtime_graph->getConstDataByTensor(axis);
- for (int32_t i = 0; i < num_dims_size_spits - 1; ++i)
+ assert(axis_data);
+
+ int32_t axis_value = (kernels::getTensorData<int32_t>(axis_data))[0];
+ if (axis_value < 0)
+ axis_value += Tensor::num_dims(input);
+
+ assert(axis_value >= 0);
+ assert(axis_value < Tensor::num_dims(input));
+
+ switch (Tensor::element_type(input))
{
- if (sizes_data[i] != -1)
+#ifndef DIS_FLOAT
+ case DataType::FLOAT32:
{
- sum += sizes_data[i];
+ return splitImpl<float>(cur_op, input, axis_value, runtime_graph);
}
- else
+#endif // DIS_FLOAT
+#ifndef DIS_QUANT
+ case DataType::S8:
{
- count_neg_dim++;
+ return splitImpl<int8_t>(cur_op, input, axis_value, runtime_graph);
}
- }
- assert(count_neg_dim < 2);
- assert(size_splits()->shape().num_elements() == num_split);
-
- // TODO: enable it only if kernel with dynamic shapes
- auto output_shape = input()->shape();
- for (int32_t i = 0; i < num_split; ++i)
- {
- if (sizes_data[i] == -1)
+ case DataType::S16:
{
- output_shape.dim(_axis_value) = input()->shape().dim(_axis_value) - sum;
+ return splitImpl<int16_t>(cur_op, input, axis_value, runtime_graph);
}
- else
+#endif // DIS_QUANT
+ case DataType::S32:
{
- output_shape.dim(_axis_value) = sizes_data[i];
+ return splitImpl<int32_t>(cur_op, input, axis_value, runtime_graph);
}
- _outputs[i]->resize(output_shape);
- }
-}
-
-void SplitV::execute() const
-{
- tflite::SplitParams params{};
- params.num_split = _outputs.size();
- params.axis = _axis_value;
-
-#define TF_LITE_SPLIT(scalar) \
- { \
- VectorOfTensors<scalar, false> all_outputs(_outputs); \
- tflite::optimized_ops::Split(params, getTensorShape(input()), getTensorData<scalar>(input()), \
- all_outputs.shapes(), all_outputs.data()); \
- }
-
- switch (input()->element_type())
- {
- case DataType::FLOAT32:
- TF_LITE_SPLIT(float);
- break;
- case DataType::U8:
- TF_LITE_SPLIT(uint8_t);
- break;
- case DataType::S16:
- TF_LITE_SPLIT(int16_t);
- break;
default:
- assert(false && "Unsupported type.");
+ assert(false && "Unsupported type");
}
-#undef TF_LITE_SPLIT
}
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/SplitV.h b/onert-micro/luci-interpreter/src/kernels/SplitV.h
deleted file mode 100644
index 0f9d31229..000000000
--- a/onert-micro/luci-interpreter/src/kernels/SplitV.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_SPLIT_V_H
-#define LUCI_INTERPRETER_KERNELS_SPLIT_V_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class SplitV : public Kernel
-{
-public:
- SplitV(const Tensor *input, const Tensor *size_splits, const Tensor *axis,
- std::vector<Tensor *> outputs);
-
- const Tensor *input() const { return _inputs[0]; }
- const Tensor *size_splits() const { return _inputs[1]; }
- const Tensor *axis() const { return _inputs[2]; }
- Tensor *output(int index) const { return _outputs[index]; }
-
- void configure() override;
- void execute() const override;
-
-private:
- int32_t _axis_value{};
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_SPLIT_V_H
diff --git a/onert-micro/luci-interpreter/src/kernels/SplitV.test.cpp b/onert-micro/luci-interpreter/src/kernels/SplitV.test.cpp
index 035bc2122..d2e7d19a2 100644
--- a/onert-micro/luci-interpreter/src/kernels/SplitV.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/SplitV.test.cpp
@@ -15,98 +15,73 @@
* limitations under the License.
*/
-#include "kernels/SplitV.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/split_v/SplitVKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
using namespace testing;
+class SplitVTest : public ::testing::Test
+{
+ // Do nothing
+};
+
template <typename T>
-void Check(int axis, std::initializer_list<int32_t> splits_size,
- std::initializer_list<int32_t> input_shape, std::initializer_list<T> input_data,
- std::vector<std::vector<T>> output_data)
+std::vector<std::vector<T>> checkSplitKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- constexpr DataType element_type = getElementType<T>();
-
- auto num_splits = static_cast<int32_t>(splits_size.size());
- Tensor input_tensor =
- makeInputTensor<element_type>(input_shape, input_data, memory_manager.get());
- Tensor sizes_tensor =
- makeInputTensor<DataType::S32>({num_splits}, splits_size, memory_manager.get());
- Tensor axis_tensor = makeInputTensor<DataType::S32>({}, {axis}, memory_manager.get());
-
- std::vector<Tensor> output_tensors;
- output_tensors.reserve(num_splits);
- for (int i = 0; i < num_splits; ++i)
- {
- output_tensors.emplace_back(makeOutputTensor(element_type));
- }
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- std::vector<Tensor *> output_tensor_ptrs(num_splits);
- for (int i = 0; i < num_splits; ++i)
- {
- output_tensor_ptrs[i] = &output_tensors[i];
- }
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
+
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
- SplitV kernel(&input_tensor, &sizes_tensor, &axis_tensor, std::move(output_tensor_ptrs));
- kernel.configure();
- for (int i = 0; i < num_splits; ++i)
+ // Set input data
{
- memory_manager->allocate_memory(output_tensors[i]);
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
}
- kernel.execute();
- for (int i = 0; i < num_splits; ++i)
+ runtime_module.execute();
+
+ assert(main_runtime_graph->getNumOfOutputTensors() == 3);
+
+ std::vector<std::vector<T>> result;
+
+ for (int i = 0; i < 3; ++i)
{
- auto tmp = extractTensorData<T>(output_tensors[i]);
- EXPECT_THAT(extractTensorData<T>(output_tensors[i]),
- ::testing::ElementsAreArray(output_data[i]));
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(i));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(i) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ result.push_back(output_data_vector);
}
+
+ return result;
}
-template <typename T> class SplitVTest : public ::testing::Test
+TEST_F(SplitVTest, MainTest_P)
{
-};
+ test_kernel::TestDataSplitVKernel<float> test_data_kernel;
+ const auto output_data_vector = checkSplitKernel(&test_data_kernel);
-using DataTypes = ::testing::Types<float, uint8_t, int16_t>;
-TYPED_TEST_SUITE(SplitVTest, DataTypes);
-
-TYPED_TEST(SplitVTest, ThreeDimensional)
-{
- Check<TypeParam>(
- /*axis=*/0, /*splits_size=*/{1, 2}, {3, 3, 3},
- {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27},
- {
- {1, 2, 3, 4, 5, 6, 7, 8, 9}, //
- {10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27} //
- });
- Check<TypeParam>(
- /*axis=*/1, /*splits_size=*/{1, 2}, {3, 3, 3},
- {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27},
- {
- {1, 2, 3, 10, 11, 12, 19, 20, 21}, //
- {4, 5, 6, 7, 8, 9, 13, 14, 15, 16, 17, 18, 22, 23, 24, 25, 26, 27} //
- });
- Check<TypeParam>(
- /*axis=*/2, /*splits_size=*/{1, 2}, {3, 3, 3},
- {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27},
- {
- {1, 4, 7, 10, 13, 16, 19, 22, 25}, //
- {2, 3, 5, 6, 8, 9, 11, 12, 14, 15, 17, 18, 20, 21, 23, 24, 26, 27} //
- });
+ for (int i = 0; i < 3; ++i)
+ {
+ EXPECT_THAT(output_data_vector[i], test_data_kernel.get_output_data_by_index(i));
+ }
}
+// TODO: add negative tests?
+
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Sqrt.cpp b/onert-micro/luci-interpreter/src/kernels/Sqrt.cpp
index 3c1bc0341..eed50dfaf 100644
--- a/onert-micro/luci-interpreter/src/kernels/Sqrt.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Sqrt.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Sqrt.h b/onert-micro/luci-interpreter/src/kernels/Sqrt.h
index d17023445..4034655ed 100644
--- a/onert-micro/luci-interpreter/src/kernels/Sqrt.h
+++ b/onert-micro/luci-interpreter/src/kernels/Sqrt.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Sqrt.test.cpp b/onert-micro/luci-interpreter/src/kernels/Sqrt.test.cpp
index 914b3af7d..96835fbfc 100644
--- a/onert-micro/luci-interpreter/src/kernels/Sqrt.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Sqrt.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Square.cpp b/onert-micro/luci-interpreter/src/kernels/Square.cpp
index 39c0d0604..6386b91f2 100644
--- a/onert-micro/luci-interpreter/src/kernels/Square.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Square.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Square.h b/onert-micro/luci-interpreter/src/kernels/Square.h
index 0277b4e6c..73ed5a707 100644
--- a/onert-micro/luci-interpreter/src/kernels/Square.h
+++ b/onert-micro/luci-interpreter/src/kernels/Square.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/SquaredDifference.h b/onert-micro/luci-interpreter/src/kernels/SquaredDifference.h
index 8aac9eba2..9327caf93 100644
--- a/onert-micro/luci-interpreter/src/kernels/SquaredDifference.h
+++ b/onert-micro/luci-interpreter/src/kernels/SquaredDifference.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Squeeze.test.cpp b/onert-micro/luci-interpreter/src/kernels/Squeeze.test.cpp
index ace02b5e1..1bc0b6459 100644
--- a/onert-micro/luci-interpreter/src/kernels/Squeeze.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Squeeze.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/StridedSlice.cpp b/onert-micro/luci-interpreter/src/kernels/StridedSlice.cpp
index 654fd3cd0..3968fb972 100644
--- a/onert-micro/luci-interpreter/src/kernels/StridedSlice.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/StridedSlice.cpp
@@ -15,135 +15,122 @@
* limitations under the License.
*/
-#include "kernels/StridedSlice.h"
-
+#include "Builders.h"
#include "kernels/Utils.h"
+#include "MISOKernel.h"
-#include <tensorflow/lite/kernels/internal/reference/strided_slice.h>
+#include "PALStridedSlice.h"
namespace luci_interpreter
{
-
-namespace kernels
+namespace
{
-StridedSlice::StridedSlice(const Tensor *input, const Tensor *begin, const Tensor *end,
- const Tensor *strides, Tensor *output, const StridedSliceParams &params)
- : KernelWithParams<StridedSliceParams>({input, begin, end, strides}, {output}, params)
+luci_interpreter_pal::StridedSliceParams
+buildStridedSliceParams(int32_t dims, const int32_t *begin, const int32_t *end,
+ const int32_t *strides, const circle::StridedSliceOptions *options)
{
-}
+ luci_interpreter_pal::StridedSliceParams op_params;
+ op_params.start_indices_count = dims;
+ op_params.stop_indices_count = dims;
+ op_params.strides_count = dims;
-void StridedSlice::configure()
-{
- assert(begin()->shape().num_dims() == 1);
- assert(end()->shape().num_dims() == 1);
- assert(strides()->shape().num_dims() == 1);
- assert(input()->element_type() == output()->element_type());
- assert(begin()->element_type() == DataType::S32);
- assert(end()->element_type() == DataType::S32);
- assert(strides()->element_type() == DataType::S32);
- assert(input()->shape().num_dims() <= 4);
- if (params().ellipsis_mask != 0)
- {
- assert(false && "ellipsis_mask is not implemented yet.");
- }
- if (params().new_axis_mask != 0)
- {
- assert(false && "new_axis_mask is not implemented yet.");
- }
- if (input()->element_type() == DataType::U8)
+ for (int i = 0; i < dims; ++i)
{
- assert(input()->scale() == output()->scale());
- assert(input()->zero_point() == output()->zero_point());
+ op_params.start_indices[i] = begin[i];
+ op_params.stop_indices[i] = end[i];
+ op_params.strides[i] = strides[i];
}
- tflite::StridedSliceParams op_params{};
- op_params.start_indices_count = input()->shape().num_dims();
- op_params.stop_indices_count = input()->shape().num_dims();
- op_params.strides_count = input()->shape().num_dims();
- for (int i = 0; i < input()->shape().num_dims(); i++)
- {
- op_params.start_indices[i] = getTensorData<int32_t>(begin())[i];
- op_params.stop_indices[i] = getTensorData<int32_t>(end())[i];
- op_params.strides[i] = getTensorData<int32_t>(strides())[i];
- }
- op_params.begin_mask = params().begin_mask;
+ op_params.begin_mask = options->begin_mask();
op_params.ellipsis_mask = 0;
- op_params.end_mask = params().end_mask;
+ op_params.end_mask = options->end_mask();
op_params.new_axis_mask = 0;
- op_params.shrink_axis_mask = params().shrink_axis_mask;
- std::vector<int32_t> output_shape_vector;
- for (int i = 0; i < input()->shape().num_dims(); i++)
- {
- int idx = input()->shape().num_dims() - i - 1;
- int32_t stride = getTensorData<int32_t>(strides())[idx];
- assert(stride != 0);
- int32_t begin = ::tflite::strided_slice::StartForAxis(op_params, getTensorShape(input()), idx);
- int32_t end =
- ::tflite::strided_slice::StopForAxis(op_params, getTensorShape(input()), idx, begin);
-
- const bool shrink_axis = params().shrink_axis_mask & (1 << idx);
- if (shrink_axis)
- {
- end = begin + 1;
- }
-
- int32_t dim_shape = std::ceil((end - begin) / static_cast<float>(stride));
- dim_shape = dim_shape < 0 ? 0 : dim_shape;
- if (!shrink_axis)
- {
- output_shape_vector.push_back(dim_shape);
- }
- }
- // TODO: enable it only if kernel with dynamic shapes
- Shape output_shape = Shape(output_shape_vector.size());
- for (size_t i = 0; i < output_shape_vector.size(); i++)
- {
- output_shape.dim(i) = output_shape_vector[output_shape_vector.size() - i - 1];
- }
- output()->resize(output_shape);
+ op_params.shrink_axis_mask = options->shrink_axis_mask();
+ return op_params;
}
-void StridedSlice::execute() const
+} // namespace
+
+void configure_kernel_CircleStridedSlice(const circle::Operator *cur_op,
+ BaseRuntimeGraph *runtime_graph)
{
- tflite::StridedSliceParams op_params{};
- op_params.start_indices_count = input()->shape().num_dims();
- op_params.stop_indices_count = input()->shape().num_dims();
- op_params.strides_count = input()->shape().num_dims();
+ kernels::MISOKernel miso_kernel(cur_op, runtime_graph);
- for (int i = 0; i < input()->shape().num_dims(); i++)
- {
- op_params.start_indices[i] = getTensorData<int32_t>(begin())[i];
- op_params.stop_indices[i] = getTensorData<int32_t>(end())[i];
- op_params.strides[i] = getTensorData<int32_t>(strides())[i];
- }
- op_params.begin_mask = params().begin_mask;
- op_params.ellipsis_mask = 0;
- op_params.end_mask = params().end_mask;
- op_params.new_axis_mask = 0;
- op_params.shrink_axis_mask = params().shrink_axis_mask;
+ const circle::Tensor *input = miso_kernel.input1();
+ const circle::Tensor *begin = miso_kernel.input2();
+ const circle::Tensor *end = miso_kernel.input3();
+ const circle::Tensor *strides = miso_kernel.input4();
+
+ LUCI_INTERPRETER_CHECK(strides != nullptr);
+
+ const circle::Tensor *output = miso_kernel.output();
+
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(begin) == DataType::S32);
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(end) == DataType::S32);
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(strides) == DataType::S32);
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(input) == Tensor::element_type(output));
+}
+
+void execute_kernel_CircleStridedSlice(const circle::Operator *cur_op,
+ BaseRuntimeGraph *runtime_graph)
+{
+ kernels::MISOKernel miso_kernel(cur_op, runtime_graph);
+
+ const circle::Tensor *input = miso_kernel.input1();
+ const circle::Tensor *begin = miso_kernel.input2();
+ const circle::Tensor *end = miso_kernel.input3();
+ const circle::Tensor *strides = miso_kernel.input4();
+ const circle::Tensor *output = miso_kernel.output();
+
+ const int32_t dims = Tensor::num_dims(input);
+
+ const uint8_t *input_data = runtime_graph->getDataByTensor(input);
+ const int32_t *begin_data =
+ kernels::getTensorData<int32_t>(runtime_graph->getConstDataByTensor(begin));
+ const int32_t *end_data =
+ kernels::getTensorData<int32_t>(runtime_graph->getConstDataByTensor(end));
+ const int32_t *strides_data =
+ kernels::getTensorData<int32_t>(runtime_graph->getConstDataByTensor(strides));
+ uint8_t *output_data = runtime_graph->getDataByTensor(output);
- switch (input()->element_type())
+ LUCI_INTERPRETER_CHECK(input_data != nullptr);
+ LUCI_INTERPRETER_CHECK(begin_data != nullptr);
+ LUCI_INTERPRETER_CHECK(end_data != nullptr);
+ LUCI_INTERPRETER_CHECK(strides_data != nullptr);
+ LUCI_INTERPRETER_CHECK(output_data != nullptr);
+
+ const auto *options = cur_op->builtin_options_as_StridedSliceOptions();
+
+ auto op_params = buildStridedSliceParams(dims, begin_data, end_data, strides_data, options);
+
+ switch (Tensor::element_type(input))
{
+#ifndef DIS_FLOAT
case DataType::FLOAT32:
- tflite::reference_ops::StridedSlice(op_params, getTensorShape(input()),
- getTensorData<float>(input()), getTensorShape(output()),
- getTensorData<float>(output()));
+ luci_interpreter_pal::StridedSlice(op_params, kernels::getTensorShape(input),
+ kernels::getTensorData<float>(input_data),
+ kernels::getTensorData<float>(output_data));
break;
+#endif // DIS_FLOAT
+#ifndef DIS_QUANT
case DataType::U8:
- tflite::reference_ops::StridedSlice(op_params, getTensorShape(input()),
- getTensorData<uint8_t>(input()), getTensorShape(output()),
- getTensorData<uint8_t>(output()));
+ luci_interpreter_pal::StridedSlice(op_params, kernels::getTensorShape(input), input_data,
+ output_data);
+ break;
+ case DataType::S8:
+ luci_interpreter_pal::StridedSlice(op_params, kernels::getTensorShape(input), input_data,
+ output_data);
break;
+#endif
case DataType::S32:
- tflite::reference_ops::StridedSlice(op_params, getTensorShape(input()),
- getTensorData<int32_t>(input()), getTensorShape(output()),
- getTensorData<int32_t>(output()));
+ luci_interpreter_pal::StridedSlice(op_params, kernels::getTensorShape(input),
+ kernels::getTensorData<int32_t>(input_data),
+ kernels::getTensorData<int32_t>(output_data));
break;
default:
- assert(false && "Unsupported type.");
+ assert(false && "Unsupported type");
}
}
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/StridedSlice.h b/onert-micro/luci-interpreter/src/kernels/StridedSlice.h
deleted file mode 100644
index d8e8e4fc0..000000000
--- a/onert-micro/luci-interpreter/src/kernels/StridedSlice.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_STRIDEDSLICE_H
-#define LUCI_INTERPRETER_KERNELS_STRIDEDSLICE_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class StridedSlice : public KernelWithParams<StridedSliceParams>
-{
-public:
- StridedSlice(const Tensor *input, const Tensor *begin, const Tensor *end, const Tensor *strides,
- Tensor *output, const StridedSliceParams &params);
-
- const Tensor *input() const { return _inputs[0]; }
- const Tensor *begin() const { return _inputs[1]; }
- const Tensor *end() const { return _inputs[2]; }
- const Tensor *strides() const { return _inputs[3]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_STRIDEDSLICE_H
diff --git a/onert-micro/luci-interpreter/src/kernels/StridedSlice.test.cpp b/onert-micro/luci-interpreter/src/kernels/StridedSlice.test.cpp
index 44da107b8..3aa2285c5 100644
--- a/onert-micro/luci-interpreter/src/kernels/StridedSlice.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/StridedSlice.test.cpp
@@ -1,6 +1,5 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,99 +14,62 @@
* limitations under the License.
*/
-#include "kernels/StridedSlice.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/strided_slice/StridedSliceKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
using namespace testing;
-TEST(StridedSliceTest, Float)
+class StridedSliceTest : public ::testing::Test
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+ // Do nothing
+};
- Shape input_shape{2, 3, 2};
- std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
- Shape begin_shape{3};
- std::vector<int32_t> begin_data{0, 0, 0};
- Shape end_shape{3};
- std::vector<int32_t> end_data{1, 3, 2};
- Shape strides_shape{3};
- std::vector<int32_t> strides_data{1, 1, 1};
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
- Tensor begin_tensor =
- makeInputTensor<DataType::S32>(begin_shape, begin_data, memory_manager.get());
- Tensor end_tensor = makeInputTensor<DataType::S32>(end_shape, end_data, memory_manager.get());
- Tensor strides_tensor =
- makeInputTensor<DataType::S32>(strides_shape, strides_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+template <typename T>
+std::vector<T> checkStridedSliceKernel(test_kernel::TestDataBase<T> *test_data_base)
+{
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- StridedSliceParams params{};
- params.begin_mask = 0;
- params.end_mask = 0;
- params.ellipsis_mask = 0;
- params.new_axis_mask = 0;
- params.shrink_axis_mask = 1;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- StridedSlice kernel(&input_tensor, &begin_tensor, &end_tensor, &strides_tensor, &output_tensor,
- params);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
- std::vector<int32_t> output_shape{3, 2};
- std::vector<float> output_data{1, 2, 3, 4, 5, 6};
- EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
-}
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
-TEST(StridedSliceTest, Uint8)
-{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+ runtime_module.execute();
- Shape input_shape{2, 3, 2};
- std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
- Shape begin_shape{3};
- std::vector<int32_t> begin_data{0, 0, 0};
- Shape end_shape{3};
- std::vector<int32_t> end_data{1, 3, 2};
- Shape strides_shape{3};
- std::vector<int32_t> strides_data{1, 1, 1};
- Tensor input_tensor =
- makeInputTensor<DataType::U8>(input_shape, 1.0f, 0, input_data, memory_manager.get());
- Tensor begin_tensor =
- makeInputTensor<DataType::S32>(begin_shape, begin_data, memory_manager.get());
- Tensor end_tensor = makeInputTensor<DataType::S32>(end_shape, end_data, memory_manager.get());
- Tensor strides_tensor =
- makeInputTensor<DataType::S32>(strides_shape, strides_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U8, 1.0f, 0);
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
- StridedSliceParams params{};
- params.begin_mask = 0;
- params.end_mask = 0;
- params.ellipsis_mask = 0;
- params.new_axis_mask = 0;
- params.shrink_axis_mask = 1;
-
- StridedSlice kernel(&input_tensor, &begin_tensor, &end_tensor, &strides_tensor, &output_tensor,
- params);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
+}
- std::vector<int32_t> output_shape{3, 2};
- std::vector<float> output_data{1, 2, 3, 4, 5, 6};
- EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(output_data));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
+TEST_F(StridedSliceTest, MainTest_P)
+{
+ test_kernel::TestDataStridedSliceKernel<float> test_data_kernel;
+ std::vector<float> output_data_vector = checkStridedSliceKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
+// TODO: add negative tests?
+
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Sub.cpp b/onert-micro/luci-interpreter/src/kernels/Sub.cpp
index 7b02c1e25..5eaed325a 100644
--- a/onert-micro/luci-interpreter/src/kernels/Sub.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Sub.cpp
@@ -14,150 +14,147 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-#include "kernels/Sub.h"
+#include "Builders.h"
#include "kernels/Utils.h"
-#include "PALSub.h"
+#include "kernels/BinaryOpCommon.h"
-#include <tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h>
+#include "PALSub.h"
namespace luci_interpreter
{
-namespace kernels
-{
-Sub::Sub(const Tensor *input1, const Tensor *input2, Tensor *output, const SubParams &params)
- : KernelWithParams<SubParams>({input1, input2}, {output}, params)
+void configure_kernel_CircleSub(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
+
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+ Tensor::element_type(kernel.input2()));
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+ Tensor::element_type(kernel.input2()));
+#ifndef DIS_QUANT
+ if (Tensor::element_type(kernel.input1()) == DataType::S16)
+ {
+ LUCI_INTERPRETER_CHECK(Tensor::zero_points(kernel.input1()).size() == 1 &&
+ Tensor::zero_points(kernel.input2()).size() == 1);
+ LUCI_INTERPRETER_CHECK(Tensor::zero_point(kernel.input1()) == 0 &&
+ Tensor::zero_point(kernel.input2()) == 0 &&
+ Tensor::zero_point(kernel.output()) == 0);
+ }
+#endif // DIS_QUANT
}
-void Sub::configure()
+void execute_kernel_CircleSub(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- LUCI_INTERPRETER_CHECK(!(input1()->element_type() != input2()->element_type()))
- LUCI_INTERPRETER_CHECK(!(input1()->element_type() != output()->element_type()))
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(calculateShapeForBroadcast(input1()->shape(), input2()->shape()));
-}
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
-void Sub::execute() const
-{
- switch (input1()->element_type())
+ const auto *options = cur_op->builtin_options_as_SubOptions();
+
+ luci_interpreter::RuntimeShape input_shape1 =
+ kernels::getTensorRuntimeShape(kernel.input1(), runtime_graph);
+ luci_interpreter::RuntimeShape input_shape2 =
+ kernels::getTensorRuntimeShape(kernel.input2(), runtime_graph);
+
+ bool is_inplace = runtime_graph->is_inplace_op(cur_op);
+
+ switch (Tensor::element_type(kernel.input1()))
{
+#ifndef DIS_FLOAT
case DataType::FLOAT32:
- evalFloat();
- break;
+ {
+ auto tiso_func = luci_interpreter_pal::Sub<float>;
+
+ auto broadcast_tiso_func = luci_interpreter_pal::BroadcastSub4DSlow<float>;
+ if (is_inplace)
+ {
+ kernels::evalTISOInplaceKernel<float>(tiso_func, broadcast_tiso_func, &kernel, options,
+ std::move(input_shape1), std::move(input_shape2));
+ }
+ else
+ {
+ kernels::TISOData kernel_data = kernel.readData();
+ kernels::evalTISOKernel<float>(tiso_func, broadcast_tiso_func, &kernel, &kernel_data,
+ options, std::move(input_shape1), std::move(input_shape2));
+ }
+ }
+ break;
+#endif // DIS_FLOAT
case DataType::S64:
- evalInteger<int64_t>();
- break;
+ {
+ auto tiso_func = luci_interpreter_pal::Sub<int64_t>;
+
+ auto broadcast_tiso_func = luci_interpreter_pal::BroadcastSub4DSlow<int64_t>;
+
+ if (is_inplace)
+ {
+ kernels::evalTISOInplaceKernel<int64_t>(tiso_func, broadcast_tiso_func, &kernel, options,
+ std::move(input_shape1), std::move(input_shape2));
+ }
+ else
+ {
+ kernels::TISOData kernel_data = kernel.readData();
+ kernels::evalTISOKernel<int64_t>(tiso_func, broadcast_tiso_func, &kernel, &kernel_data,
+ options, std::move(input_shape1), std::move(input_shape2));
+ }
+ }
+ break;
case DataType::S32:
- evalInteger<int32_t>();
- break;
+ {
+ auto tiso_func = luci_interpreter_pal::Sub<int32_t>;
+
+ auto broadcast_tiso_func = luci_interpreter_pal::BroadcastSub4DSlow<int32_t>;
+
+ if (is_inplace)
+ {
+ kernels::evalTISOInplaceKernel<int32_t>(tiso_func, broadcast_tiso_func, &kernel, options,
+ std::move(input_shape1), std::move(input_shape2));
+ }
+ else
+ {
+ kernels::TISOData kernel_data = kernel.readData();
+ kernels::evalTISOKernel<int32_t>(tiso_func, broadcast_tiso_func, &kernel, &kernel_data,
+ options, std::move(input_shape1), std::move(input_shape2));
+ }
+ }
+ break;
+// TODO: fix it
+#if 0
+#ifndef DIS_QUANT
case DataType::U8:
- evalQuantized();
- break;
+ {
+ auto tiso_func = [](const tflite::ArithmeticParams &params,
+ const tflite::RuntimeShape &input1_shape, const uint8_t *input1_data,
+ const tflite::RuntimeShape &input2_shape, const uint8_t *input2_data,
+ const tflite::RuntimeShape &output_shape, uint8_t *output_data) {
+ tflite::reference_ops::Sub(params, input1_shape, input1_data, input2_shape, input2_data,
+ output_shape, output_data);
+ };
+ auto broadcast_tiso_func =
+ [](const tflite::ArithmeticParams &params, const tflite::RuntimeShape &input1_shape,
+ const uint8_t *input1_data, const tflite::RuntimeShape &input2_shape,
+ const uint8_t *input2_data, const tflite::RuntimeShape &output_shape,
+ uint8_t *output_data) {
+ tflite::reference_ops::BroadcastSubSlow(params, input1_shape, input1_data, input2_shape,
+ input2_data, output_shape, output_data);
+ };
+ if (is_inplace)
+ {
+ kernels::evalTISOInplaceQuantizedKernel<uint8_t>(tiso_func, broadcast_tiso_func, &kernel,
+ options);
+ }
+ else
+ {
+ kernels::TISOData kernel_data = kernel.readData();
+ kernels::evalTISOQuantizedKernel<uint8_t>(tiso_func, broadcast_tiso_func, &kernel,
+ &kernel_data, options);
+ }
+ }
+ break;
+#endif // DIS_QUANT
+#endif // 0
default:
assert(false && "Unsupported type.");
}
}
-void Sub::evalFloat() const
-{
- tflite::ArithmeticParams params{};
- fillArithmeticActivationRange<float>(params, _params.activation);
-
- const bool need_broadcast = tflite::reference_ops::ProcessBroadcastShapes(
- getTensorShape(input1()), getTensorShape(input2()), &params);
-
- if (need_broadcast)
- {
- tflite::reference_ops::BroadcastSubSlow(
- params, getTensorShape(input1()), getTensorData<float>(input1()), getTensorShape(input2()),
- getTensorData<float>(input2()), getTensorShape(output()), getTensorData<float>(output()));
- }
- else
- {
- luci_interpreter_pal::Sub(params, getTensorShape(input1()), getTensorData<float>(input1()),
- getTensorShape(input2()), getTensorData<float>(input2()),
- getTensorShape(output()), getTensorData<float>(output()));
- }
-}
-
-template <typename T> void Sub::evalInteger() const
-{
- tflite::ArithmeticParams params{};
- fillArithmeticActivationRange<T>(params, _params.activation);
-
- const bool need_broadcast = tflite::reference_ops::ProcessBroadcastShapes(
- getTensorShape(input1()), getTensorShape(input2()), &params);
-
- if (need_broadcast)
- {
- tflite::reference_ops::BroadcastSubSlow(
- params, getTensorShape(input1()), getTensorData<T>(input1()), getTensorShape(input2()),
- getTensorData<T>(input2()), getTensorShape(output()), getTensorData<T>(output()));
- }
- else
- {
- tflite::reference_ops::Sub(params, getTensorShape(input1()), getTensorData<T>(input1()),
- getTensorShape(input2()), getTensorData<T>(input2()),
- getTensorShape(output()), getTensorData<T>(output()));
- }
-}
-
-void Sub::evalQuantized() const
-{
- const auto input1_scale = static_cast<double>(input1()->scale());
- const auto input2_scale = static_cast<double>(input2()->scale());
- const auto output_scale = static_cast<double>(output()->scale());
-
- const int left_shift = 20;
- const double twice_max_input_scale = 2 * std::max(input1_scale, input2_scale);
- const double real_input1_multiplier = input1_scale / twice_max_input_scale;
- const double real_input2_multiplier = input2_scale / twice_max_input_scale;
- const double real_output_multiplier = twice_max_input_scale / ((1 << left_shift) * output_scale);
-
- int32_t input1_multiplier{}, input2_multiplier{}, output_multiplier{};
- int input1_shift{}, input2_shift{}, output_shift{};
- quantizeMultiplierSmallerThanOneExp(real_input1_multiplier, &input1_multiplier, &input1_shift);
- quantizeMultiplierSmallerThanOneExp(real_input2_multiplier, &input2_multiplier, &input2_shift);
- quantizeMultiplierSmallerThanOneExp(real_output_multiplier, &output_multiplier, &output_shift);
-
- int32_t activation_min{};
- int32_t activation_max{};
- calculateActivationRangeQuantized(_params.activation, output(), &activation_min, &activation_max);
-
- tflite::ArithmeticParams params{};
- params.left_shift = left_shift;
- // The kernel expects inputs' zero points to be negated.
- params.input1_offset = -input1()->zero_point(); // Note the '-'.
- params.input1_multiplier = input1_multiplier;
- params.input1_shift = input1_shift;
- params.input2_offset = -input2()->zero_point(); // Note the '-'.
- params.input2_multiplier = input2_multiplier;
- params.input2_shift = input2_shift;
- params.output_offset = output()->zero_point();
- params.output_multiplier = output_multiplier;
- params.output_shift = output_shift;
- params.quantized_activation_min = activation_min;
- params.quantized_activation_max = activation_max;
-
- const bool need_broadcast = tflite::reference_ops::ProcessBroadcastShapes(
- getTensorShape(input1()), getTensorShape(input2()), &params);
-
- if (need_broadcast)
- {
- tflite::reference_ops::BroadcastSubSlow(
- params, getTensorShape(input1()), getTensorData<uint8_t>(input1()), getTensorShape(input2()),
- getTensorData<uint8_t>(input2()), getTensorShape(output()), getTensorData<uint8_t>(output()));
- }
- else
- {
- tflite::reference_ops::Sub(params, getTensorShape(input1()), getTensorData<uint8_t>(input1()),
- getTensorShape(input2()), getTensorData<uint8_t>(input2()),
- getTensorShape(output()), getTensorData<uint8_t>(output()));
- }
-}
-
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Sub.h b/onert-micro/luci-interpreter/src/kernels/Sub.h
deleted file mode 100644
index f9cedff6f..000000000
--- a/onert-micro/luci-interpreter/src/kernels/Sub.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_SUB_H
-#define LUCI_INTERPRETER_KERNELS_SUB_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Sub : public KernelWithParams<SubParams>
-{
-public:
- Sub(const Tensor *input1, const Tensor *input2, Tensor *output, const SubParams &params);
-
- const Tensor *input1() const { return _inputs[0]; }
- const Tensor *input2() const { return _inputs[1]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-
-private:
- void evalFloat() const;
- template <typename T> void evalInteger() const;
- void evalQuantized() const;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_SUB_H
diff --git a/onert-micro/luci-interpreter/src/kernels/Sub.test.cpp b/onert-micro/luci-interpreter/src/kernels/Sub.test.cpp
index 9abafd49a..ff267b12c 100644
--- a/onert-micro/luci-interpreter/src/kernels/Sub.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Sub.test.cpp
@@ -15,252 +15,138 @@
* limitations under the License.
*/
-#include "kernels/Sub.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/sub/FloatSubKernel.h"
+#include "luci_interpreter/test_models/sub/IntSubKernel.h"
+#include "luci_interpreter/test_models/sub/NegSubKernel.h"
-#include <algorithm>
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
using namespace testing;
-using std::pair;
-using std::vector;
-using std::transform;
-using std::initializer_list;
class SubTest : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-// for quantized Add, the error shouldn't exceed step
-float GetTolerance(float min, float max)
-{
- float kQuantizedStep = (max - min) / 255.0;
- return kQuantizedStep;
-}
-
-TEST_F(SubTest, Uint8)
+template <typename T> std::vector<T> checkSubKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- Shape base_shape = {2, 3, 1, 2};
- vector<float> base_data = {-0.3f, 2.3f, 0.9f, 0.5f, 0.8f, -1.1f,
- 1.2f, 2.8f, -1.6f, 0.0f, 0.7f, -2.2f};
- vector<Shape> test_shapes = {{1, 1, 3, 2}, {1, 3, 1, 2}, {2, 1, 3, 1}, {2, 3, 1, 1}};
- vector<float> test_data = {0.2f, 0.3f, -0.4f, 0.5f, 1.0f, 0.9f};
- vector<vector<int32_t>> output_shapes = {{2, 3, 3, 2}, {2, 3, 1, 2}, {2, 3, 3, 2}, {2, 3, 1, 2}};
- vector<vector<float>> output_data = {
- {-0.5f, 2.0f, 0.1f, 1.8f, -1.3f, 1.4f, 0.7f, 0.2f, 1.3f, 0.0f, -0.1f, -0.4f,
- 0.6f, -1.4f, 1.2f, -1.6f, -0.2f, -2.0f, 1.0f, 2.5f, 1.6f, 2.3f, 0.2f, 1.9f,
- -1.8f, -0.3f, -1.2f, -0.5f, -2.6f, -0.9f, 0.5f, -2.5f, 1.1f, -2.7f, -0.3f, -3.0f},
- {-0.5f, 2.0f, 1.3f, 0.0f, -0.2f, -2.0f, 1.0f, 2.5f, -1.2f, -0.5f, -0.3f, -3.0f},
- {-0.5f, 2.1f, -0.6f, 2.0f, 0.1f, 2.7f, 0.7f, 0.3f, 0.6f, 0.2f, 1.3f, 0.9f,
- 0.6f, -1.3f, 0.5f, -1.4f, 1.2f, -0.7f, 0.7f, 2.3f, 0.2f, 1.8f, 0.3f, 1.9f,
- -2.1f, -0.5f, -2.6f, -1.0f, -2.5f, -0.9f, 0.2f, -2.7f, -0.3f, -3.0f, -0.2f, -3.0f},
- {-0.5f, 2.1f, 0.6f, 0.2f, 1.2f, -0.7f, 0.7f, 2.3f, -2.6f, -1.0f, -0.2f, -3.0f}};
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- float kQuantizedTolerance = GetTolerance(-3.f, 3.f);
- pair<float, int32_t> quant_param = quantizationParams<uint8_t>(-3.f, 3.f);
- for (size_t i = 0; i < output_data.size(); ++i)
- {
- Tensor input1_tensor = makeInputTensor<DataType::U8>(
- base_shape, quant_param.first, quant_param.second, base_data, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::U8>(
- test_shapes[i], quant_param.first, quant_param.second, test_data, _memory_manager.get());
- Tensor output_tensor =
- makeOutputTensor(getElementType<uint8_t>(), quant_param.first, quant_param.second);
-
- SubParams params{};
- params.activation = Activation::NONE;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- Sub kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 2);
- EXPECT_THAT(dequantizeTensorData(output_tensor),
- FloatArrayNear(output_data[i], kQuantizedTolerance));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shapes[i]));
+ // set left input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
}
- // Inversion step for output_data, because subtract is not commutative operation
- auto multiply = [](auto &i) {
- transform(i.begin(), i.end(), i.begin(), [](auto &value) { return value * -1.0f; });
- };
- for_each(output_data.begin(), output_data.end(), multiply);
-
- // Re-run with exchanged inputs.
- for (size_t i = 0; i < output_data.size(); ++i)
+ // set right input data
{
- Tensor input1_tensor = makeInputTensor<DataType::U8>(
- test_shapes[i], quant_param.first, quant_param.second, test_data, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::U8>(
- base_shape, quant_param.first, quant_param.second, base_data, _memory_manager.get());
- Tensor output_tensor =
- makeOutputTensor(getElementType<uint8_t>(), quant_param.first, quant_param.second);
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(1));
+ std::copy(test_data_base->get_input_data_by_index(1).begin(),
+ test_data_base->get_input_data_by_index(1).end(), input_tensor_data);
+ }
- SubParams params{};
- params.activation = Activation::NONE;
+ runtime_module.execute();
- Sub kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
- EXPECT_THAT(dequantizeTensorData(output_tensor),
- FloatArrayNear(output_data[i], kQuantizedTolerance));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shapes[i]));
- }
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST_F(SubTest, Float)
+TEST_F(SubTest, Float_P)
{
- Shape base_shape = {2, 3, 1, 2};
- vector<Shape> test_shapes{{1, 1, 3, 2}, {1, 3, 1, 2}, {2, 1, 3, 1}, {2, 3, 1, 1}};
- vector<vector<int32_t>> output_shapes{{2, 3, 3, 2}, {2, 3, 1, 2}, {2, 3, 3, 2}, {2, 3, 1, 2}};
- vector<vector<float>> test_outputs = {
- {0.0f, 2.0f, 0.1f, 1.8f, 0.0f, 1.4f, 0.7f, 0.2f, 1.3f, 0.0f, 0.0f, 0.0f,
- 0.6f, 0.0f, 1.2f, 0.0f, 0.0f, 0.0f, 1.0f, 2.5f, 1.6f, 2.3f, 0.2f, 1.9f,
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 1.1f, 0.0f, 0.0f, 0.0f},
- {0.0f, 2.0f, 1.3f, 0.0f, 0.0f, 0.0f, 1.0f, 2.5f, 0.0f, 0.0f, 0.0f, 0.0f},
- {0.0f, 2.1f, 0.0f, 2.0f, 0.1f, 2.7f, 0.7f, 0.3f, 0.6f, 0.2f, 1.3f, 0.9f,
- 0.6f, 0.0f, 0.5f, 0.0f, 1.2f, 0.0f, 0.7f, 2.3f, 0.2f, 1.8f, 0.3f, 1.9f,
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
- {0.0f, 2.1f, 0.6f, 0.2f, 1.2f, 0.0f, 0.7f, 2.3f, 0.0f, 0.0f, 0.0f, 0.0f}};
-
- vector<float> input1_data{-0.3f, 2.3f, 0.9f, 0.5f, 0.8f, -1.1f,
- 1.2f, 2.8f, -1.6f, 0.0f, 0.7f, -2.2f};
- vector<float> input2_data{0.2f, 0.3f, -0.4f, 0.5f, 1.0f, 0.9f};
- for (size_t i = 0; i < test_shapes.size(); ++i)
+ // No broadcast
{
- Tensor input1_tensor =
- makeInputTensor<DataType::FLOAT32>(base_shape, input1_data, _memory_manager.get());
- Tensor input2_tensor =
- makeInputTensor<DataType::FLOAT32>(test_shapes[i], input2_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- SubParams params{};
- params.activation = Activation::RELU;
-
- Sub kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(test_outputs[i], 0.0001f))
- << "With shape number " << i;
-
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shapes[i]));
+ const bool is_with_broadcast = false;
+ test_kernel::TestDataFloatSub test_data_float_kernel(is_with_broadcast);
+ std::vector<float> output_data_vector = checkSubKernel(&test_data_float_kernel);
+ EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+ test_data_float_kernel.get_output_data_by_index(0), 0.0001f));
}
-}
-
-template <loco::DataType DType> void CheckInteger(luci_interpreter::IMemoryManager *memory_manager)
-{
- using dtype = typename loco::DataTypeImpl<DType>::Type;
- Shape base_shape = {2, 3, 1, 2};
- std::vector<Shape> test_shapes{{1, 1, 3, 2}, {1, 3, 1, 2}, {2, 1, 3, 1}, {2, 3, 1, 1}};
- std::vector<std::vector<dtype>> test_outputs = {
- {0, 1, 2, 3, 0, 0, 0, 0, 4, 1, 0, 0, 0, 0, 7, 0, 3, 0,
- 0, 2, 4, 4, 0, 0, 3, 0, 10, 0, 6, 0, 3, 0, 10, 2, 6, 0},
- {0, 1, 4, 1, 3, 0, 0, 2, 10, 0, 6, 0},
- {0, 0, 0, 1, 2, 5, 0, 0, 0, 0, 4, 3, 0, 0, 3, 0, 7, 0,
- 2, 4, 0, 2, 0, 0, 8, 0, 6, 0, 1, 0, 8, 2, 6, 0, 1, 0},
- {0, 0, 0, 0, 7, 0, 2, 4, 6, 0, 1, 0}};
- std::vector<dtype> input1_data{-1, 2, 1, 0, 4, -5, 1, 3, 7, -1, 7, 1};
- std::vector<dtype> input2_data{4, 1, -3, -1, 1, 6};
- for (size_t i = 0; i < test_shapes.size(); ++i)
+ // With broadcast
{
- Tensor input1_tensor = makeInputTensor<DType>(base_shape, input1_data, memory_manager);
- Tensor input2_tensor = makeInputTensor<DType>(test_shapes[i], input2_data, memory_manager);
- Tensor output_tensor = makeOutputTensor(DType);
-
- SubParams params{};
- params.activation = Activation::RELU;
-
- Sub kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- EXPECT_THAT(extractTensorData<dtype>(output_tensor), test_outputs[i])
- << "With shape number " << i;
+ const bool is_with_broadcast = true;
+ test_kernel::TestDataFloatSub test_data_float_kernel(is_with_broadcast);
+ std::vector<float> output_data_vector = checkSubKernel(&test_data_float_kernel);
+ EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+ test_data_float_kernel.get_output_data_by_index(0), 0.0001f));
}
-};
-
-TEST_F(SubTest, SInt32)
-{
- CheckInteger<loco::DataType::S32>(_memory_manager.get());
- SUCCEED();
}
-TEST_F(SubTest, SInt64)
+TEST_F(SubTest, INT_P)
{
- CheckInteger<loco::DataType::S64>(_memory_manager.get());
- SUCCEED();
+ // No broadcast
+ {
+ const bool is_with_broadcast = false;
+ test_kernel::TestDataIntSub test_data_kernel(is_with_broadcast);
+ const auto output_data_vector = checkSubKernel<int32_t>(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+ }
+ // With broadcast
+ {
+ const bool is_with_broadcast = true;
+ test_kernel::TestDataIntSub test_data_kernel(is_with_broadcast);
+ const auto output_data_vector = checkSubKernel<int32_t>(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+ }
}
-TEST_F(SubTest, Input_Output_Type_NEG)
+TEST_F(SubTest, Inputs_type_mismatch_NEG)
{
- Tensor input1_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::S32>({1}, {2}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- SubParams params{};
- params.activation = Activation::RELU;
-
- Sub kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::NegTestDataInputsTypeMismatchSubKernel test_data_kernel;
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST_F(SubTest, Invalid_Output_Type_NEG)
+TEST_F(SubTest, Input_output_type_mismatch_NEG)
{
- Tensor input1_tensor = makeInputTensor<DataType::S64>({1}, {1}, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::S64>({1}, {2}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S32);
-
- SubParams params{};
- params.activation = Activation::RELU;
-
- Sub kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::NegTestDataInputOutputTypeMismatchSubKernel test_data_kernel;
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST_F(SubTest, Invalid_Input_Type_NEG)
+TEST_F(SubTest, No_quant_params_NEG)
{
- Tensor input1_tensor = makeInputTensor<DataType::U64>({1}, {1}, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::U64>({1}, {2}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U64);
-
- SubParams params{};
- params.activation = Activation::RELU;
-
- Sub kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- EXPECT_ANY_THROW(kernel.execute());
+ test_kernel::NegTestDataNoQuantParamsSubKernel test_data_kernel;
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
-TEST_F(SubTest, Mismatching_Input_Int_Types_NEG)
-{
- Tensor input1_tensor = makeInputTensor<DataType::S32>({1}, {1}, _memory_manager.get());
- Tensor input2_tensor = makeInputTensor<DataType::S64>({1}, {2}, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::S32);
-
- SubParams params{};
- params.activation = Activation::NONE;
-
- Sub kernel(&input1_tensor, &input2_tensor, &output_tensor, params);
- EXPECT_ANY_THROW(kernel.configure());
-}
+// TODO: add tests for U8 and S16
+// TODO: add tests for inplace optimizations for all types
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/TISOKernel.h b/onert-micro/luci-interpreter/src/kernels/TISOKernel.h
new file mode 100644
index 000000000..48dec74e3
--- /dev/null
+++ b/onert-micro/luci-interpreter/src/kernels/TISOKernel.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_KERNELS_TISO_KERNEL_H
+#define LUCI_INTERPRETER_KERNELS_TISO_KERNEL_H
+
+#include "Builders.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+struct TISOData
+{
+ uint8_t *input1_data = nullptr;
+ uint8_t *input2_data = nullptr;
+ uint8_t *output_data = nullptr;
+};
+
+// Two input single output kernel
+class TISOKernel
+{
+public:
+ TISOKernel() = delete;
+
+ explicit TISOKernel(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+ : _runtime_graph(runtime_graph)
+ {
+ const auto input1_index = cur_op->inputs()->operator[](0);
+ const auto input2_index = cur_op->inputs()->operator[](1);
+ const auto output_index = cur_op->outputs()->operator[](0);
+
+ assert(input1_index != -1);
+ assert(input2_index != -1);
+ assert(output_index != -1);
+
+ _input1_tensor = _runtime_graph->getCircleTensorByIndex(input1_index);
+ _input2_tensor = _runtime_graph->getCircleTensorByIndex(input2_index);
+ _output_tensor = _runtime_graph->getCircleTensorByIndex(output_index);
+
+ assert(_input1_tensor != nullptr);
+ assert(_input2_tensor != nullptr);
+ assert(_output_tensor != nullptr);
+ }
+
+ const circle::Tensor *input1() const { return _input1_tensor; }
+ const circle::Tensor *input2() const { return _input2_tensor; }
+ const circle::Tensor *output() const { return _output_tensor; }
+
+ BaseRuntimeGraph *runtime_graph() const { return _runtime_graph; }
+
+ TISOData readData()
+ {
+ auto *input1_data = _runtime_graph->getDataByTensor(_input1_tensor);
+ if (input1_data == nullptr)
+ input1_data = _runtime_graph->getConstDataByTensor(_input1_tensor);
+ assert(input1_data);
+
+ auto *input2_data = _runtime_graph->getDataByTensor(_input2_tensor);
+ if (input2_data == nullptr)
+ input2_data = _runtime_graph->getConstDataByTensor(_input2_tensor);
+ assert(input2_data);
+
+ auto *output_data = _runtime_graph->getDataByTensor(_output_tensor);
+ assert(output_data);
+
+ return {input1_data, input2_data, output_data};
+ }
+
+ TISOData readInplaceData(uint8_t *&inplace_data_ptr, circle::Tensor *&input_inplace_tensor)
+ {
+ auto *input1_data = _runtime_graph->getDataByTensor(_input1_tensor);
+ if (input1_data != nullptr)
+ {
+ inplace_data_ptr = const_cast<uint8_t *>(input1_data);
+ input_inplace_tensor = const_cast<circle::Tensor *>(_input1_tensor);
+ }
+ if (input1_data == nullptr)
+ input1_data = _runtime_graph->getConstDataByTensor(_input1_tensor);
+
+ assert(input1_data);
+
+ auto *input2_data = _runtime_graph->getDataByTensor(_input2_tensor);
+ if (inplace_data_ptr == nullptr)
+ {
+ assert(input2_data != nullptr);
+ inplace_data_ptr = const_cast<uint8_t *>(input2_data);
+ input_inplace_tensor = const_cast<circle::Tensor *>(_input2_tensor);
+ }
+ if (input2_data == nullptr)
+ input2_data = _runtime_graph->getConstDataByTensor(_input2_tensor);
+ assert(input2_data);
+
+ assert(_runtime_graph->getDataByTensor(_output_tensor) == nullptr);
+
+ auto *output_data = inplace_data_ptr;
+ assert(output_data);
+
+ return {input1_data, input2_data, output_data};
+ }
+
+private:
+ const circle::Tensor *_input1_tensor;
+ const circle::Tensor *_input2_tensor;
+ const circle::Tensor *_output_tensor;
+
+ BaseRuntimeGraph *_runtime_graph;
+};
+
+} // namespace kernels
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_KERNELS_TISO_KERNEL_H
diff --git a/onert-micro/luci-interpreter/src/kernels/Tanh.cpp b/onert-micro/luci-interpreter/src/kernels/Tanh.cpp
index 3acb22e93..809a91457 100644
--- a/onert-micro/luci-interpreter/src/kernels/Tanh.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Tanh.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,81 +14,191 @@
* limitations under the License.
*/
-#include "kernels/Tanh.h"
-
+#include "Builders.h"
#include "kernels/Utils.h"
+#include "SISOKernel.h"
-#include <tensorflow/lite/kernels/internal/reference/tanh.h>
+#include "PALTanh.h"
namespace luci_interpreter
{
-namespace kernels
-{
-Tanh::Tanh(const Tensor *input, Tensor *output) : Kernel({input}, {output}) {}
+#ifndef DIS_QUANT
-void Tanh::configure()
+namespace
+{
+void calculateArithmeticData(const circle::Tensor *input, const circle::Tensor *output,
+ int32_t &input_zero_point, int32_t &input_range_radius,
+ int32_t &input_multiplier, int &input_left_shift)
{
- LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
- if (input()->element_type() == DataType::U8)
+ const auto input_dtype = Tensor::element_type(input);
+ switch (input_dtype)
{
- populateLookupTable();
+ // TODO: enable it
+#if 0
+ case DataType::S8:
+ {
+ static constexpr int input_integer_bits = 4;
+ const double input_real_multiplier = static_cast<double>(Tensor::scale(input)) *
+ static_cast<double>(1 << (31 - input_integer_bits));
+
+ const double q = std::frexp(input_real_multiplier, &input_left_shift);
+ input_multiplier = static_cast<int32_t>(std::round(q * (1ll << 31)));
+ input_range_radius = kernels::calculateInputRadius(input_integer_bits, input_left_shift, 31);
+ }
+ break;
+#endif
+ case DataType::S16:
+ {
+ static constexpr int input_integer_bits = 3;
+ static constexpr int output_fractional_bits = 15;
+
+ // These operators are implemented in fixed-point arithmetic,
+ // which intrinsically wants symmetric ranges (zero_point==0)
+ // and power-of-two scales (power-of-two is abbreviated below as POT).
+ // While more general support would be possible by means of rescaling,
+ // that would add some overhead and some loss of accuracy and wouldn't
+ // be used at the moment as current quantized LSTM applications are
+ // happy with symmetric, power-of-two-scales quantization. So we just
+ // implement that narrow case only for now.
+
+ int input_scale_log2_rounded;
+ bool param_scale_pot = kernels::checkedLog2(Tensor::scale(input), &input_scale_log2_rounded);
+
+ input_left_shift = (15 - input_integer_bits) + input_scale_log2_rounded;
+ param_scale_pot &= (input_left_shift == 0 || input_left_shift == 1);
+
+ if (param_scale_pot)
+ {
+ input_multiplier = 0;
+ }
+ else
+ {
+ // Calculate multiplier to change input scale to 1/(3*4096)
+ // as required by the table lookup.
+ // The number 3.0 in the multiplier comes from here,
+ // because the interval is [-10.7, 10.7] instead of [-8, 8].
+ // So, in this scaling +/-2^17 represents +/-10.7.
+
+ double multiplier = static_cast<double>(Tensor::scale(input)) * 4096.0 * 3.0;
+ input_left_shift = 0;
+
+ while (multiplier <= 32767.0 / 2.0 && input_left_shift <= 30)
+ {
+ input_left_shift++;
+ multiplier = multiplier * 2.0;
+ }
+
+ input_multiplier = static_cast<int32_t>(multiplier);
+ }
+
+ int output_scale_log2_rounded;
+ kernels::checkedLog2(Tensor::scale(output), &output_scale_log2_rounded);
+ assert(output_scale_log2_rounded == -output_fractional_bits);
+ }
+ break;
+ default:
+ assert(false && "Unsupported type");
}
- // TODO: enable it only if kernel with dynamic shapes
- output()->resize(input()->shape());
}
-void Tanh::execute() const
+} // namespace
+
+void evalInteger(const circle::Tensor *input, const circle::Tensor *output,
+ BaseRuntimeGraph *runtime_graph)
{
- switch (input()->element_type())
+ int32_t input_zero_point = 0;
+ int32_t input_range_radius = 0;
+ int32_t input_multiplier = 0;
+ int input_left_shift = 0;
+
+ calculateArithmeticData(input, output, input_zero_point, input_range_radius, input_multiplier,
+ input_left_shift);
+
+ const auto *input_data = runtime_graph->getDataByTensor(input);
+ assert(input_data);
+
+ auto *output_data = runtime_graph->getDataByTensor(output);
+ assert(output_data);
+
+ const int flat_size = kernels::getTensorRuntimeShape(input, runtime_graph).flatSize();
+
+ const auto input_dtype = Tensor::element_type(input);
+ switch (input_dtype)
{
- case DataType::FLOAT32:
- evalFloat();
+ // TODO: enable it
+#if 0
+ case DataType::S8:
+ luci_interpreter_pal::Tanh(
+ input_zero_point, input_range_radius, input_multiplier, input_left_shift,
+ flat_size, kernels::getTensorData<int8_t>(input_data), kernels::getTensorData<int8_t>(output_data));
break;
- case DataType::U8:
- evalQuantized();
+#endif // 0
+ case DataType::S16:
+ luci_interpreter_pal::Tanh(input_multiplier, input_left_shift, flat_size,
+ kernels::getTensorData<int16_t>(input_data),
+ kernels::getTensorData<int16_t>(output_data));
break;
default:
- assert(false && "Unsupported type.");
+ assert(false && "Not support yet");
}
}
+#endif // DIS_QUANT
-void Tanh::evalFloat() const
+void configure_kernel_CircleTanh(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- tflite::reference_ops::Tanh(getTensorShape(input()), getTensorData<float>(input()),
- getTensorShape(output()), getTensorData<float>(output()));
-}
+ kernels::SISOKernel kernel(cur_op, runtime_graph);
-void Tanh::evalQuantized() const
-{
- const int size = tflite::MatchingFlatSize(getTensorShape(input()), getTensorShape(output()));
- uint8_t *output_data = getTensorData<uint8_t>(output());
- const uint8_t *input_data = getTensorData<uint8_t>(input());
- for (int i = 0; i < size; ++i)
- {
- output_data[i] = getTableValue(input_data[i]);
- }
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input()) ==
+ Tensor::element_type(kernel.output()));
}
-void Tanh::populateLookupTable()
+void execute_kernel_CircleTanh(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- const auto input_scale = static_cast<double>(input()->scale());
- const auto input_zero_point = static_cast<int32_t>(input()->zero_point());
- const auto output_scale = static_cast<double>(output()->scale());
- const auto output_zero_point = static_cast<int32_t>(output()->zero_point());
- const float inverse_scale = 1 / output_scale;
- int32_t maxval = std::numeric_limits<uint8_t>::max();
- int32_t minval = std::numeric_limits<uint8_t>::min();
- for (int32_t val = minval; val <= maxval; ++val)
+ kernels::SISOKernel kernel(cur_op, runtime_graph);
+
+ const auto *input_data = runtime_graph->getDataByTensor(kernel.input());
+ assert(input_data);
+
+ auto *output_data = runtime_graph->getDataByTensor(kernel.output());
+
+ bool is_inplace = runtime_graph->is_inplace_op(cur_op);
+
+ switch (Tensor::element_type(kernel.input()))
{
- const float dequantized = input_scale * (val - input_zero_point);
- const float transformed = std::tanh(dequantized);
- const float rescaled = std::round(transformed * inverse_scale);
- const int32_t quantized = static_cast<int32_t>(rescaled + output_zero_point);
- setTableValue(static_cast<uint8_t>(std::max(std::min(maxval, quantized), minval)),
- static_cast<uint8_t>(val));
+#ifndef DIS_FLOAT
+ case DataType::FLOAT32:
+ {
+ const float *input_data_float = kernels::getTensorData<float>(input_data);
+ float *output_data_float = kernels::getTensorData<float>(output_data);
+ if (is_inplace)
+ {
+ output_data_float = const_cast<float *>(input_data_float);
+ }
+
+ assert(output_data_float);
+
+ const int flat_size =
+ kernels::getTensorRuntimeShape(kernel.input(), runtime_graph).flatSize();
+
+ luci_interpreter_pal::Tanh(flat_size, input_data_float, output_data_float);
+ break;
+ }
+#endif // DIS_FLOAT
+#ifndef DIS_QUANT
+ case DataType::S16:
+ // TODO: enable it
+#if 0
+ case DataType::S8:
+#endif
+ evalInteger(kernel.input(), kernel.output(), runtime_graph);
+ break;
+#endif // DIS_QUANT
+ default:
+ assert(false && "Unsupported type");
}
-}
-} // namespace kernels
+ if (is_inplace)
+ runtime_graph->makeInplaceOperation(kernel.input(), kernel.output());
+}
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Tanh.h b/onert-micro/luci-interpreter/src/kernels/Tanh.h
deleted file mode 100644
index af87bf3c5..000000000
--- a/onert-micro/luci-interpreter/src/kernels/Tanh.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_TANH_H
-#define LUCI_INTERPRETER_KERNELS_TANH_H
-
-#include "core/Kernel.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Tanh : public Kernel
-{
-public:
- Tanh(const Tensor *input, Tensor *output);
-
- const Tensor *input() const { return _inputs[0]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-
-private:
- void evalFloat() const;
- void evalQuantized() const;
- void populateLookupTable();
- void setTableValue(uint8_t value, uint8_t idx) { _table[idx] = value; };
- uint8_t getTableValue(uint8_t idx) const { return _table[idx]; };
-
-private:
- uint8_t _table[256]{};
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_TANH_H
diff --git a/onert-micro/luci-interpreter/src/kernels/Tanh.test.cpp b/onert-micro/luci-interpreter/src/kernels/Tanh.test.cpp
index bfae479a9..ff55a95a1 100644
--- a/onert-micro/luci-interpreter/src/kernels/Tanh.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Tanh.test.cpp
@@ -15,14 +15,14 @@
* limitations under the License.
*/
-#include "kernels/Tanh.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/tanh/FloatTanhKernel.h"
+#include "luci_interpreter/test_models/tanh/NegTanhKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
@@ -30,135 +30,60 @@ using namespace testing;
class TanhTest : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-TEST_F(TanhTest, Float)
+template <typename T> std::vector<T> checkTanhKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- Shape input_shape{1, 2, 4, 1};
- std::vector<float> input_data{
- 0, -6, 2, 4, //
- 3, -2, 10, 1, //
- };
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- Tanh kernel(&input_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- std::vector<float> ref_output_data{
- 0, -0.9999877, 0.9640275, 0.999329, //
- 0.99505475, -0.9640275, 1, 0.7615941, //
- };
- EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
-}
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
-TEST_F(TanhTest, Uint8)
-{
- float kMin = -1;
- float kMax = 127.f / 128.f;
- float kTanhTolerance = 2 * (1. / 256);
- std::pair<float, int32_t> input_quant_param = quantizationParams<uint8_t>(8 * kMin, 8 * kMax);
- std::pair<float, int32_t> output_quant_param = quantizationParams<uint8_t>(kMin, kMax);
- std::vector<float> input_data{
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- };
- Tensor input_tensor =
- makeInputTensor<DataType::U8>({2, 6, 4, 1}, input_quant_param.first, input_quant_param.second,
- input_data, _memory_manager.get());
- Tensor output_tensor =
- makeOutputTensor(DataType::U8, output_quant_param.first, output_quant_param.second);
-
- Tanh kernel(&input_tensor, &output_tensor);
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- kernel.execute();
-
- std::vector<float> ref_output_data{
- 0.0, -0.999987, 0.964027, 0.999329, //
- -0.999329, -0.96402, 0.99999, 0.76159, //
- 0.0, -0.999987, 0.964027, 0.999329, //
- -0.999329, -0.96402, 0.99999, 0.76159, //
- 0.0, -0.999987, 0.964027, 0.999329, //
- -0.999329, -0.96402, 0.99999, 0.76159, //
- 0.0, -0.999987, 0.964027, 0.999329, //
- -0.999329, -0.96402, 0.99999, 0.76159, //
- 0.0, -0.999987, 0.964027, 0.999329, //
- -0.999329, -0.96402, 0.99999, 0.76159, //
- 0.0, -0.999987, 0.964027, 0.999329, //
- -0.999329, -0.96402, 0.99999, 0.76159, //
- };
- std::vector<int32_t> ref_output_shape{2, 6, 4, 1};
- EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data, kTanhTolerance));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
+
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
+
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
+
+ runtime_module.execute();
+
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
+
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST_F(TanhTest, InputTypeInvalid_NEG)
+TEST_F(TanhTest, Float_P)
{
- std::vector<int64_t> input_data{
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- };
- Tensor input_tensor =
- makeInputTensor<DataType::S64>({2, 6, 4, 1}, input_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- Tanh kernel(&input_tensor, &output_tensor);
- _memory_manager->allocate_memory(output_tensor);
- EXPECT_ANY_THROW(kernel.execute());
+ test_kernel::TestDataFloatTanh test_data_kernel;
+ std::vector<float> output_data_vector = checkTanhKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+ test_data_kernel.get_output_data_by_index(0), 0.0001f));
}
-TEST_F(TanhTest, InputOutputMismatch_NEG)
+TEST_F(TanhTest, Input_output_type_mismatch_NEG)
{
- std::vector<float> input_data{
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- };
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>({2, 6, 4, 1}, input_data, _memory_manager.get());
- Tensor output_tensor = makeOutputTensor(DataType::U8);
-
- Tanh kernel(&input_tensor, &output_tensor);
- EXPECT_ANY_THROW(kernel.configure());
+ test_kernel::NegTestDataInputOutputTypeMismatchTanhKernel test_data_kernel;
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
+// TODO: add S16 test
+
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/TestUtils.cpp b/onert-micro/luci-interpreter/src/kernels/TestUtils.cpp
index 78caa3738..7e4bf7dce 100644
--- a/onert-micro/luci-interpreter/src/kernels/TestUtils.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/TestUtils.cpp
@@ -27,78 +27,6 @@ namespace testing
using ::testing::FloatNear;
using ::testing::Matcher;
-Tensor makeOutputTensor(DataType element_type) { return Tensor(element_type, {}, {}, ""); }
-
-Tensor makeOutputTensor(DataType element_type, float scale, int32_t zero_point)
-{
- return Tensor(element_type, {}, {{scale}, {zero_point}}, "");
-}
-
-std::vector<float> dequantizeTensorData(const Tensor &tensor)
-{
- if (tensor.element_type() == DataType::U8)
- {
- std::vector<uint8_t> data = extractTensorData<uint8_t>(tensor);
- return dequantize(data.data(), data.size(), tensor.scale(), tensor.zero_point());
- }
- if (tensor.element_type() == DataType::S8)
- {
- std::vector<int8_t> data = extractTensorData<int8_t>(tensor);
- return dequantize(data.data(), data.size(), tensor.scale(), tensor.zero_point());
- }
- else if (tensor.element_type() == DataType::S16)
- {
- // S16 quantization is symmetric, so zero point should be zero.
- for (auto zp : tensor.zero_points())
- {
- (void)zp;
- assert(zp == 0);
- }
-
- std::vector<int16_t> data = extractTensorData<int16_t>(tensor);
- if (tensor.scales().size() == 1)
- {
- return dequantize(data.data(), data.size(), tensor.scale(), 0);
- }
-
- // quantize_dimension breaks shape into two parts:
- // inner dimensions that contains continuous data with one quantization type
- // outer dimensions that contains other dimensions
- const Shape shape = tensor.shape();
- const int32_t quantized_dimension = tensor.quantized_dimension();
- assert(quantized_dimension < shape.num_dims());
- size_t outer_dims_size = 1;
- int32_t quant_dim_size = shape.dim(quantized_dimension);
- size_t inner_dims_size = 1;
- assert(quant_dim_size == tensor.scales().size());
-
- for (int i = 0; i < quantized_dimension; ++i)
- outer_dims_size *= shape.dim(i);
- for (int i = quantized_dimension + 1; i < shape.num_dims(); ++i)
- inner_dims_size *= shape.dim(i);
-
- assert(shape.num_elements() == outer_dims_size * quant_dim_size * inner_dims_size);
-
- std::vector<float> dequantized_data;
- dequantized_data.reserve(shape.num_elements());
- for (size_t outer_it = 0; outer_it < outer_dims_size; ++outer_it)
- for (int32_t channel = 0; channel < quant_dim_size; ++channel)
- {
- float scale = tensor.scales()[channel];
- size_t offset = inner_dims_size * (quant_dim_size * outer_it + channel);
- std::vector<float> part_dequantized_data =
- dequantize(data.data() + offset, inner_dims_size, scale, 0);
- dequantized_data.insert(dequantized_data.end(), part_dequantized_data.begin(),
- part_dequantized_data.end());
- }
- return dequantized_data;
- }
- else
- {
- assert(false && "Unsupported type.");
- }
-}
-
Matcher<std::vector<float>> FloatArrayNear(const std::vector<float> &values, float max_abs_error)
{
std::vector<Matcher<float>> matchers;
@@ -110,17 +38,6 @@ Matcher<std::vector<float>> FloatArrayNear(const std::vector<float> &values, flo
return ElementsAreArray(matchers);
}
-std::vector<int32_t> extractTensorShape(const Tensor &tensor)
-{
- std::vector<int32_t> result;
- int dims = tensor.shape().num_dims();
- for (int i = 0; i < dims; i++)
- {
- result.push_back(tensor.shape().dim(i));
- }
- return result;
-}
-
} // namespace testing
} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/TestUtils.h b/onert-micro/luci-interpreter/src/kernels/TestUtils.h
index 1f5a0c308..492044c89 100644
--- a/onert-micro/luci-interpreter/src/kernels/TestUtils.h
+++ b/onert-micro/luci-interpreter/src/kernels/TestUtils.h
@@ -19,7 +19,6 @@
#define LUCI_INTERPRETER_KERNELS_TESTUTILS_H
#include "luci_interpreter/core/Tensor.h"
-#include "luci_interpreter/MemoryManager.h"
#include <type_traits>
@@ -33,262 +32,10 @@ namespace kernels
namespace testing
{
-template <typename T>
-std::vector<T> quantize(const float *data, size_t num_elements, float scale, int32_t zero_point);
-
-template <DataType DT>
-Tensor makeInputTensor(const Shape &shape, const std::vector<typename DataTypeImpl<DT>::Type> &data,
- IMemoryManager *memory_manager)
-{
- Tensor tensor(DT, shape, {}, "");
- memory_manager->allocate_memory(tensor);
- tensor.writeData(data.data(), data.size() * sizeof(typename DataTypeImpl<DT>::Type));
- return tensor;
-}
-
-/**
- * @brief Create layer-wise quantized tensor
- * @tparam DT base integer data type, for example DataType::U8, DataType::S16, DataType::S64
- * @param shape desired tensor shape
- * @param scale scale of quantized number
- * @param zero_point zero point of quantized number, should be 0 for signed datatypes
- * @param data floating point data for quantization
- * @param memory_manager memory manager for allocating memory to tensor
- * @return created tensor
- */
-template <DataType DT>
-Tensor makeInputTensor(const Shape &shape, float scale, int32_t zero_point,
- const std::vector<float> &data, IMemoryManager *memory_manager)
-{
- using NativeT = typename DataTypeImpl<DT>::Type;
- Tensor tensor(DT, shape, {{scale}, {zero_point}}, "");
- std::vector<NativeT> quantized_data =
- quantize<NativeT>(data.data(), data.size(), scale, zero_point);
- memory_manager->allocate_memory(tensor);
- tensor.writeData(quantized_data.data(), quantized_data.size() * sizeof(NativeT));
- return tensor;
-}
-
-/**
- * @brief Create channel-wise quantized tensor
- * @tparam DT base integer data type, for example DataType::U8, DataType::S16, DataType::S64
- * @param shape desired tensor shape
- * @param scales scales of quantized number
- * @param zero_points zero points of quantized number, should be 0 for signed datatypes
- * @param quantize_dimension dimension to apply quantization along. Usually channels/output channels
- * @param data floating point data for quantization
- * @param memory_manager memory manager for allocating memory to tensor
- * @return created tensor
- */
-template <DataType DT>
-Tensor makeInputTensor(const Shape &shape, const std::vector<float> &scales,
- const std::vector<int32_t> &zero_points, int quantized_dimension,
- const std::vector<float> &data, IMemoryManager *memory_manager)
-{
- using NativeT = typename DataTypeImpl<DT>::Type;
- assert(quantized_dimension < shape.num_dims());
- Tensor tensor(DT, shape, {scales, zero_points, quantized_dimension}, "");
-
- // quantize_dimension breaks shape into two parts:
- // inner dimensions that contains continuous data with one quantization type
- // outer dimensions that contains other dimensions
- size_t outer_dims_size = 1;
- int32_t quant_dim_size = shape.dim(quantized_dimension);
- size_t inner_dims_size = 1;
- assert(quant_dim_size == scales.size());
- assert(quant_dim_size == zero_points.size());
-
- for (int i = 0; i < quantized_dimension; ++i)
- outer_dims_size *= shape.dim(i);
- for (int i = quantized_dimension + 1; i < shape.num_dims(); ++i)
- inner_dims_size *= shape.dim(i);
-
- assert(shape.num_elements() == outer_dims_size * quant_dim_size * inner_dims_size);
-
- std::vector<NativeT> quantized_data;
- quantized_data.reserve(shape.num_elements());
- for (size_t outer_it = 0; outer_it < outer_dims_size; ++outer_it)
- for (int32_t channel = 0; channel < quant_dim_size; ++channel)
- {
- int32_t zero_point = zero_points[channel];
- float scale = scales[channel];
- size_t offset = inner_dims_size * (quant_dim_size * outer_it + channel);
- std::vector<NativeT> part_quantized_data =
- quantize<NativeT>(data.data() + offset, inner_dims_size, scale, zero_point);
- quantized_data.insert(quantized_data.end(), part_quantized_data.begin(),
- part_quantized_data.end());
- }
- assert(quantized_data.size() == shape.num_elements());
- memory_manager->allocate_memory(tensor);
- tensor.writeData(quantized_data.data(), quantized_data.size() * sizeof(NativeT));
- return tensor;
-}
-
-Tensor makeOutputTensor(DataType element_type);
-Tensor makeOutputTensor(DataType element_type, float scale, int32_t zero_point);
-
-std::vector<int32_t> extractTensorShape(const Tensor &tensor);
-
-// Returns the corresponding DataType given the type T.
-template <typename T> constexpr DataType getElementType()
-{
- if (std::is_same<T, float>::value)
- return DataType::FLOAT32;
- if (std::is_same<T, double>::value)
- return DataType::FLOAT64;
- if (std::is_same<T, uint8_t>::value)
- return DataType::U8;
- if (std::is_same<T, uint16_t>::value)
- return DataType::U16;
- if (std::is_same<T, uint32_t>::value)
- return DataType::U32;
- if (std::is_same<T, uint64_t>::value)
- return DataType::U64;
- if (std::is_same<T, int8_t>::value)
- return DataType::S8;
- if (std::is_same<T, int16_t>::value)
- return DataType::S16;
- if (std::is_same<T, int32_t>::value)
- return DataType::S32;
- if (std::is_same<T, int64_t>::value)
- return DataType::S64;
- if (std::is_same<T, bool>::value)
- return DataType::BOOL;
- return DataType::Unknown;
-}
-
-template <typename T> std::vector<T> extractTensorData(const Tensor &tensor)
-{
- const auto *data_ptr = tensor.data<T>();
- return std::vector<T>(data_ptr, data_ptr + tensor.shape().num_elements());
-}
-
-std::vector<float> dequantizeTensorData(const Tensor &tensor);
-
// Array version of `::testing::FloatNear` matcher.
::testing::Matcher<std::vector<float>> FloatArrayNear(const std::vector<float> &values,
float max_abs_error = 1.0e-5f);
-template <typename T>
-std::vector<T> quantize(const float *data, size_t num_elements, float scale, int32_t zero_point)
-{
- static_assert(std::is_integral<T>::value, "Integral type expected.");
-
- float q_min{}, q_max{};
- if (std::is_signed<T>::value)
- {
- q_min = -std::numeric_limits<T>::max();
- q_max = std::numeric_limits<T>::max();
- }
- else
- {
- q_min = 0;
- q_max = std::numeric_limits<T>::max();
- }
-
- std::vector<T> q;
- for (size_t i = 0; i < num_elements; ++i)
- {
- const auto &f = data[i];
- q.push_back(static_cast<T>(
- std::max<float>(q_min, std::min<float>(q_max, std::round(zero_point + (f / scale))))));
- }
- return q;
-}
-
-template <typename T>
-std::vector<float> dequantize(const T *data, size_t num_elements, float scale, int32_t zero_point)
-{
- static_assert(std::is_integral<T>::value, "Integral type expected.");
- std::vector<float> f;
- for (size_t i = 0; i < num_elements; ++i)
- {
- const T &q = data[i];
- f.push_back(scale * (q - zero_point));
- }
- return f;
-}
-
-// NOTE Returns scale and zero point for _asymmetric_ range (both signed and unsigned).
-template <typename T> std::pair<float, int32_t> quantizationParams(float f_min, float f_max)
-{
- static_assert(std::is_integral<T>::value, "Integral type expected.");
- int32_t zero_point = 0;
- float scale = 0;
- const T qmin = std::numeric_limits<T>::lowest();
- const T qmax = std::numeric_limits<T>::max();
- const float qmin_double = qmin;
- const float qmax_double = qmax;
- // 0 should always be a representable value. Let's assume that the initial
- // min,max range contains 0.
- assert(f_max >= 0);
- assert(f_min <= 0);
- if (f_min == f_max)
- {
- // Special case where the min,max range is a point. Should be {0}.
- assert(f_max == 0);
- assert(f_min == 0);
- return {scale, zero_point};
- }
-
- // General case.
- //
- // First determine the scale.
- scale = (f_max - f_min) / (qmax_double - qmin_double);
-
- // Zero-point computation.
- // First the initial floating-point computation. The zero-point can be
- // determined from solving an affine equation for any known pair
- // (real value, corresponding quantized value).
- // We know two such pairs: (rmin, qmin) and (rmax, qmax).
- // The arithmetic error on the zero point computed from either pair
- // will be roughly machine_epsilon * (sum of absolute values of terms)
- // so we want to use the variant that adds the smaller terms.
- const float zero_point_from_min = qmin_double - f_min / scale;
- const float zero_point_from_max = qmax_double - f_max / scale;
-
- const float zero_point_from_min_error = std::abs(qmin_double) + std::abs(f_min / scale);
-
- const float zero_point_from_max_error = std::abs(qmax_double) + std::abs(f_max / scale);
-
- const float zero_point_double = zero_point_from_min_error < zero_point_from_max_error
- ? zero_point_from_min
- : zero_point_from_max;
-
- // Now we need to nudge the zero point to be an integer
- // (our zero points are integer, and this is motivated by the requirement
- // to be able to represent the real value "0" exactly as a quantized value,
- // which is required in multiple places, for example in Im2col with SAME
- // padding).
-
- T nudged_zero_point = 0;
- if (zero_point_double < qmin_double)
- {
- nudged_zero_point = qmin;
- }
- else if (zero_point_double > qmax_double)
- {
- nudged_zero_point = qmax;
- }
- else
- {
- nudged_zero_point = static_cast<T>(std::round(zero_point_double));
- }
-
- // The zero point should always be in the range of quantized value,
- // // [qmin, qmax].
- assert(qmax >= nudged_zero_point);
- assert(qmin <= nudged_zero_point);
- zero_point = nudged_zero_point;
- // finally, return the values
- return {scale, zero_point};
-}
-
-inline float getTolerance(float min, float max, int quantize_steps)
-{
- return ((max - min) / quantize_steps);
-}
-
} // namespace testing
} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Transpose.cpp b/onert-micro/luci-interpreter/src/kernels/Transpose.cpp
index 06ea2353c..a6018c4ff 100644
--- a/onert-micro/luci-interpreter/src/kernels/Transpose.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Transpose.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright 2020 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,70 +15,71 @@
* limitations under the License.
*/
-#include "kernels/Transpose.h"
-
+#include "Builders.h"
+#include "TISOKernel.h"
#include "kernels/Utils.h"
-#include <tensorflow/lite/kernels/internal/reference/transpose.h>
+#include "PALTranspose.h"
namespace luci_interpreter
{
-
-namespace kernels
+void configure_kernel_CircleTranspose(const circle::Operator *cur_op,
+ BaseRuntimeGraph *runtime_graph)
{
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
-Transpose::Transpose(const Tensor *input, const Tensor *perm, Tensor *output)
- : Kernel({input, perm}, {output})
-{
-}
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input2()) == DataType::S32);
-void Transpose::configure()
-{
- // Transpose op only supports 1D-4D input arrays.
- int dims = input()->shape().num_dims();
- const int32_t *perm_data = getTensorData<int32_t>(perm());
-
- assert(input()->shape().num_dims() <= 4);
- assert(input()->element_type() == output()->element_type());
+ const int32_t dims = Tensor::num_dims(kernel.input1());
+ const int32_t *perm_data =
+ kernels::getTensorData<int32_t>(runtime_graph->getConstDataByTensor(kernel.input2()));
- assert(perm()->shape().num_dims() == 1);
- assert(perm()->shape().dim(0) == dims);
+ // Ensure validity of the permutations tensor as a 1D tensor
+ LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.input2()) == 1);
+ LUCI_INTERPRETER_CHECK(Tensor::dim(kernel.input2(), 0) == dims);
- Shape output_shape(dims);
- for (int i = 0; i < dims; i++)
- {
- assert(perm_data[i] < dims && perm_data[i] >= 0);
- output_shape.dim(i) = input()->shape().dim(perm_data[i]);
- }
- // TODO: enable it only if kernel with dynamic shapes
-
- output()->resize(output_shape);
+ for (int idx = 0; idx < dims; ++idx)
+ LUCI_INTERPRETER_CHECK(perm_data[idx] >= 0 and perm_data[idx] < dims);
}
-void Transpose::execute() const
+void execute_kernel_CircleTranspose(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- tflite::TransposeParams params{};
- const int32_t *perm_data = getTensorData<int32_t>(perm());
- const int32_t size = perm()->shape().dim(0);
+ kernels::TISOKernel kernel(cur_op, runtime_graph);
+
+ const circle::Tensor *input = kernel.input1();
+ const circle::Tensor *perm = kernel.input2();
+ const circle::Tensor *output = kernel.output();
+
+ kernels::TISOData tiso_data = kernel.readData();
+ const int32_t *perm_data = kernels::getTensorData<int32_t>(tiso_data.input2_data);
+
+ const int32_t size = Tensor::dim(perm, 0);
+ luci_interpreter_pal::TransposeParams params;
params.perm_count = size;
- for (int i = 0; i < size; i++)
+ for (int i = 0; i < size; ++i)
params.perm[i] = perm_data[i];
- switch (input()->element_type())
+
+ switch (Tensor::element_type(input))
{
+#ifndef DIS_FLOAT
case DataType::FLOAT32:
- tflite::reference_ops::Transpose(params, getTensorShape(input()),
- getTensorData<float>(input()), getTensorShape(output()),
- getTensorData<float>(output()));
+ luci_interpreter_pal::Transpose(params, kernels::getTensorShape(input),
+ kernels::getTensorData<float>(tiso_data.input1_data),
+ kernels::getTensorShape(output),
+ kernels::getTensorData<float>(tiso_data.output_data));
break;
+#endif // DIS_FLOAT
+#ifndef DIS_QUANT
case DataType::U8:
- tflite::reference_ops::Transpose(params, getTensorShape(input()),
- getTensorData<uint8_t>(input()), getTensorShape(output()),
- getTensorData<uint8_t>(output()));
+ luci_interpreter_pal::Transpose(params, kernels::getTensorShape(input),
+ kernels::getTensorData<uint8_t>(tiso_data.input1_data),
+ kernels::getTensorShape(output),
+ kernels::getTensorData<uint8_t>(tiso_data.output_data));
break;
+#endif // DIS_QUANT
default:
- assert(false && "Unsupported type.");
+ assert(false && "Unsupported type");
}
}
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Transpose.h b/onert-micro/luci-interpreter/src/kernels/Transpose.h
deleted file mode 100644
index 5619c62ca..000000000
--- a/onert-micro/luci-interpreter/src/kernels/Transpose.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_TRANSPOSE_H
-#define LUCI_INTERPRETER_KERNELS_TRANSPOSE_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Transpose : public Kernel
-{
-public:
- Transpose(const Tensor *input, const Tensor *perm, Tensor *output);
-
- const Tensor *input() const { return _inputs[0]; }
- const Tensor *perm() const { return _inputs[1]; }
- Tensor *output() const { return _outputs[0]; }
-
- void configure() override;
- void execute() const override;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_TRANSPOSE_H
diff --git a/onert-micro/luci-interpreter/src/kernels/Transpose.test.cpp b/onert-micro/luci-interpreter/src/kernels/Transpose.test.cpp
index 8cc699361..dda521243 100644
--- a/onert-micro/luci-interpreter/src/kernels/Transpose.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Transpose.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,102 +14,62 @@
* limitations under the License.
*/
-#include "kernels/Transpose.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/transpose/TransposeKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
using namespace testing;
+class TransposeTest : public ::testing::Test
+{
+ // Do nothing
+};
+
template <typename T>
-void Check(std::initializer_list<int32_t> input_shape, std::initializer_list<int32_t> perm_shape,
- std::initializer_list<int32_t> output_shape, std::initializer_list<T> input_data,
- std::initializer_list<int32_t> perm_data, std::initializer_list<T> output_data)
+std::vector<T> checkTransposeKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- constexpr DataType element_type = getElementType<T>();
- Tensor input_tensor =
- makeInputTensor<element_type>(input_shape, input_data, memory_manager.get());
- Tensor perm_tensor = makeInputTensor<DataType::S32>(perm_shape, perm_data, memory_manager.get());
- Tensor output_tensor = makeOutputTensor(element_type);
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- Transpose kernel(&input_tensor, &perm_tensor, &output_tensor);
- kernel.configure();
- memory_manager->allocate_memory(output_tensor);
- kernel.execute();
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- EXPECT_THAT(extractTensorData<T>(output_tensor), ::testing::ElementsAreArray(output_data));
-}
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
-template <typename T> class TransposeTest : public ::testing::Test
-{
-};
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
-using DataTypes = ::testing::Types<float, uint8_t>;
-TYPED_TEST_SUITE(TransposeTest, DataTypes);
+ runtime_module.execute();
-TYPED_TEST(TransposeTest, Small3D)
-{
- Check<TypeParam>(/*input_shape=*/{2, 3, 4}, /*perm_shape=*/{3}, /*output_shape=*/{4, 2, 3},
- /*input_data=*/{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
- 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23},
- /*perm_data=*/{2, 0, 1},
- /*output_data=*/{0, 4, 8, 12, 16, 20, 1, 5, 9, 13, 17, 21,
- 2, 6, 10, 14, 18, 22, 3, 7, 11, 15, 19, 23});
-}
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
-TYPED_TEST(TransposeTest, Large4D)
-{
- Check<TypeParam>(
- /*input_shape=*/{2, 3, 4, 5}, /*perm_shape=*/{4}, /*output_shape=*/{4, 2, 3, 5},
- /*input_data=*/{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
- 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
- 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
- 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
- 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
- 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119},
- /*perm_data=*/{2, 0, 1, 3},
- /*output_data=*/{0, 1, 2, 3, 4, 20, 21, 22, 23, 24, 40, 41, 42, 43, 44,
- 60, 61, 62, 63, 64, 80, 81, 82, 83, 84, 100, 101, 102, 103, 104,
- 5, 6, 7, 8, 9, 25, 26, 27, 28, 29, 45, 46, 47, 48, 49,
- 65, 66, 67, 68, 69, 85, 86, 87, 88, 89, 105, 106, 107, 108, 109,
- 10, 11, 12, 13, 14, 30, 31, 32, 33, 34, 50, 51, 52, 53, 54,
- 70, 71, 72, 73, 74, 90, 91, 92, 93, 94, 110, 111, 112, 113, 114,
- 15, 16, 17, 18, 19, 35, 36, 37, 38, 39, 55, 56, 57, 58, 59,
- 75, 76, 77, 78, 79, 95, 96, 97, 98, 99, 115, 116, 117, 118, 119});
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TYPED_TEST(TransposeTest, Large2D)
+TEST_F(TransposeTest, MainTest_P)
{
- Check<TypeParam>(
- /*input_shape=*/{10, 12}, /*perm_shape=*/{2}, /*output_shape=*/{12, 10},
- /*input_data=*/{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
- 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
- 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
- 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
- 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
- 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119},
- /*perm_data=*/{1, 0},
- /*output_data=*/{0, 12, 24, 36, 48, 60, 72, 84, 96, 108, 1, 13, 25, 37, 49,
- 61, 73, 85, 97, 109, 2, 14, 26, 38, 50, 62, 74, 86, 98, 110,
- 3, 15, 27, 39, 51, 63, 75, 87, 99, 111, 4, 16, 28, 40, 52,
- 64, 76, 88, 100, 112, 5, 17, 29, 41, 53, 65, 77, 89, 101, 113,
- 6, 18, 30, 42, 54, 66, 78, 90, 102, 114, 7, 19, 31, 43, 55,
- 67, 79, 91, 103, 115, 8, 20, 32, 44, 56, 68, 80, 92, 104, 116,
- 9, 21, 33, 45, 57, 69, 81, 93, 105, 117, 10, 22, 34, 46, 58,
- 70, 82, 94, 106, 118, 11, 23, 35, 47, 59, 71, 83, 95, 107, 119});
+ test_kernel::TestDataTransposeKernel<float> test_data_kernel;
+ std::vector<float> output_data_vector = checkTransposeKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
+// TODO: add negative tests?
+
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/TransposeConv.h b/onert-micro/luci-interpreter/src/kernels/TransposeConv.h
index 2a9d2f1cb..cea0cf3c7 100644
--- a/onert-micro/luci-interpreter/src/kernels/TransposeConv.h
+++ b/onert-micro/luci-interpreter/src/kernels/TransposeConv.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/TransposeConv.test.cpp b/onert-micro/luci-interpreter/src/kernels/TransposeConv.test.cpp
index ff98ac0f0..4856e1b87 100644
--- a/onert-micro/luci-interpreter/src/kernels/TransposeConv.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/TransposeConv.test.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/UnidirectionalSequenceLSTM.cpp b/onert-micro/luci-interpreter/src/kernels/UnidirectionalSequenceLSTM.cpp
index 57cf9f2e1..63ef363ac 100644
--- a/onert-micro/luci-interpreter/src/kernels/UnidirectionalSequenceLSTM.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/UnidirectionalSequenceLSTM.cpp
@@ -19,7 +19,6 @@
#include "kernels/Utils.h"
#include "PALUnidirectionalSequenceLSTM.h"
-#include "PALApplyActivationToVector.h"
namespace luci_interpreter
{
@@ -47,11 +46,11 @@ bool checkedLog2(const float x, int *log2_result)
// are required for input. However, during the hidden state update phase, the
// output is the updated hidden state, which is asymmetrically quantized. Thus
// output may require zero point
-lstm::ArithmeticParams createInterGateParams(const float input1_scale, const float input2_scale,
- const float output_scale, const DataType output_type,
- const int output_zp)
+luci_interpreter_pal::ArithmeticParams
+createInterGateParams(const float input1_scale, const float input2_scale, const float output_scale,
+ const DataType output_type, const int output_zp)
{
- lstm::ArithmeticParams op_params;
+ luci_interpreter_pal::ArithmeticParams op_params;
if (output_type == DataType::S16)
{
op_params.quantized_activation_min = std::numeric_limits<int16_t>::min();
@@ -84,7 +83,7 @@ void createGateParams(const circle::Tensor *input, const circle::Tensor *input_w
{
// Input CalculateOpDataFullyConnected
{
- lstm::FullyConnectedParams input_gate_params;
+ luci_interpreter_pal::FullyConnectedParams input_gate_params;
double real_multiplier = 0.0;
int output_shift;
int32_t output_activation_min;
@@ -110,7 +109,7 @@ void createGateParams(const circle::Tensor *input, const circle::Tensor *input_w
// Recurrent CalculateOpDataFullyConnected
{
- lstm::FullyConnectedParams recurrent_gate_params;
+ luci_interpreter_pal::FullyConnectedParams recurrent_gate_params;
double real_multiplier = 0.0;
int output_shift;
int32_t output_activation_min;
@@ -246,11 +245,13 @@ void evalInt8(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph, b
#endif // DIS_QUANT
#ifndef DIS_FLOAT
-lstm::FullyConnectedParams createFcParamsFloat()
+luci_interpreter_pal::FullyConnectedParams createFcParamsFloat()
{
- lstm::FullyConnectedParams op_params;
+ luci_interpreter_pal::FullyConnectedParams op_params;
kernels::calculateActivationRange(FusedActFunc::NONE, &op_params.float_activation_min,
&op_params.float_activation_max);
+ op_params.quantized_activation_max = op_params.float_activation_max;
+ op_params.quantized_activation_min = op_params.float_activation_min;
return op_params;
}
@@ -282,9 +283,11 @@ void prepareGateParamsFloat(lstm::LSTMParameters *float_lstm_params)
float_lstm_params->output_gate_parameters = createGateParamsFloat();
// Inter gate multiplication parameters
- lstm::ArithmeticParams op_params;
+ luci_interpreter_pal::ArithmeticParams op_params;
kernels::calculateActivationRange(FusedActFunc::NONE, &op_params.float_activation_min,
&op_params.float_activation_max);
+ op_params.quantized_activation_max = op_params.float_activation_max;
+ op_params.quantized_activation_min = op_params.float_activation_min;
float_lstm_params->inter_gate_parameters.forget_cell_mul_params = op_params;
float_lstm_params->inter_gate_parameters.input_mul_params = op_params;
float_lstm_params->inter_gate_parameters.output_mul_params = op_params;
@@ -414,23 +417,25 @@ void configure_kernel_CircleUnidirectionalSequenceLSTM(const circle::Operator *c
}
void execute_kernel_CircleUnidirectionalSequenceLSTM(const circle::Operator *cur_op,
- BaseRuntimeGraph *runtime_graph, bool in_place)
+ BaseRuntimeGraph *runtime_graph)
{
const auto input_index = cur_op->inputs()->operator[](0);
assert(input_index != -1);
+ bool is_inplace = runtime_graph->is_inplace_op(cur_op);
+
const auto input = runtime_graph->getCircleTensorByIndex(input_index);
switch (Tensor::element_type(input))
{
#ifndef DIS_FLOAT
case DataType::FLOAT32:
- evalFloat(cur_op, runtime_graph, in_place);
+ evalFloat(cur_op, runtime_graph, is_inplace);
break;
#endif // DIS_FLOAT
#ifndef DIS_QUANT
case DataType::S8:
- evalInt8(cur_op, runtime_graph, in_place);
+ evalInt8(cur_op, runtime_graph, is_inplace);
break;
#endif // DIS_QUANT
default:
diff --git a/onert-micro/luci-interpreter/src/kernels/UnidirectionalSequenceLSTM.h b/onert-micro/luci-interpreter/src/kernels/UnidirectionalSequenceLSTM.h
index 8cdccc10a..38c1212c1 100644
--- a/onert-micro/luci-interpreter/src/kernels/UnidirectionalSequenceLSTM.h
+++ b/onert-micro/luci-interpreter/src/kernels/UnidirectionalSequenceLSTM.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +17,7 @@
#ifndef LUCI_INTERPRETER_KERNELS_UNIDIRECTIONAL_SEQUENCE_LSTM_H
#define LUCI_INTERPRETER_KERNELS_UNIDIRECTIONAL_SEQUENCE_LSTM_H
-#include "Utils.h"
+#include "PALUtils.h"
namespace luci_interpreter
{
@@ -185,43 +184,17 @@ private:
const circle::Tensor *internal_tensors[24];
};
-struct FullyConnectedParams
-{
- int32_t input_offset;
- int32_t weights_offset;
- int32_t output_offset;
- int32_t output_multiplier;
- int32_t output_shift;
- int32_t quantized_activation_min;
- int32_t quantized_activation_max;
- int32_t float_activation_min;
- int32_t float_activation_max;
-};
-
struct GateParameters
{
- FullyConnectedParams input_fc_params;
- FullyConnectedParams recurrent_fc_params;
-};
-
-struct ArithmeticParams
-{
- int32_t input1_offset;
- int32_t input2_offset;
- int32_t quantized_activation_min;
- int32_t quantized_activation_max;
- int32_t output_offset;
- int32_t output_multiplier;
- int32_t output_shift;
- int32_t float_activation_min;
- int32_t float_activation_max;
+ luci_interpreter_pal::FullyConnectedParams input_fc_params;
+ luci_interpreter_pal::FullyConnectedParams recurrent_fc_params;
};
struct InterGateParameters
{
- ArithmeticParams forget_cell_mul_params;
- ArithmeticParams input_mul_params;
- ArithmeticParams output_mul_params;
+ luci_interpreter_pal::ArithmeticParams forget_cell_mul_params;
+ luci_interpreter_pal::ArithmeticParams input_mul_params;
+ luci_interpreter_pal::ArithmeticParams output_mul_params;
};
struct CellStateInfo
diff --git a/onert-micro/luci-interpreter/src/kernels/UnidirectionalSequenceLSTM.test.cpp b/onert-micro/luci-interpreter/src/kernels/UnidirectionalSequenceLSTM.test.cpp
index df059cfcc..1a094ee88 100644
--- a/onert-micro/luci-interpreter/src/kernels/UnidirectionalSequenceLSTM.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/UnidirectionalSequenceLSTM.test.cpp
@@ -15,551 +15,71 @@
* limitations under the License.
*/
-#include "kernels/UnidirectionalSequenceLSTM.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/unidirectional_lstm/FloatUnidirectionalLSTMKernel.h"
+#include "luci_interpreter/test_models/unidirectional_lstm/QuantS8UnidirectionalLSTM.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
using namespace testing;
-class UnidirectionalSequenceLSTMTest : public ::testing::Test
+class UnidirectionalLSTMTest : public ::testing::Test
{
-protected:
- void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
- std::unique_ptr<IMemoryManager> _memory_manager;
+ // Do nothing
};
-// NOTE from NoCifgNoPeepholeNoProjectionNoClippingUnidirectionalLstmTest
-TEST_F(UnidirectionalSequenceLSTMTest, FloatTest)
+template <typename T>
+std::vector<T> checkUnidirectionalSequenceLSTMKernel(test_kernel::TestDataBase<T> *test_data_base)
{
- const int32_t n_batch = 1;
- const int32_t n_input = 2;
- const int32_t n_cell = 4;
- const int32_t n_output = 4;
- const int32_t sequence_length = 3;
-
- std::vector<float> input_to_input_weights = {-0.45018822, -0.02338299, -0.0870589, -0.34550029,
- 0.04266912, -0.15680569, -0.34856534, 0.43890524};
-
- std::vector<float> input_to_cell_weights = {-0.50013041, 0.1370284, 0.11810488, 0.2013163,
- -0.20583314, 0.44344562, 0.22077113, -0.29909778};
-
- std::vector<float> input_to_forget_weights = {0.09701663, 0.20334584, -0.50592935, -0.31343272,
- -0.40032279, 0.44781327, 0.01387155, -0.35593212};
-
- std::vector<float> input_to_output_weights = {-0.25065863, -0.28290087, 0.04613829, 0.40525138,
- 0.44272184, 0.03897077, -0.1556896, 0.19487578};
-
- std::vector<float> input_gate_bias = {0., 0., 0., 0.};
- std::vector<float> forget_gate_bias = {1., 1., 1., 1.};
- std::vector<float> cell_gate_bias = {0., 0., 0., 0.};
- std::vector<float> output_gate_bias = {0., 0., 0., 0.};
-
- std::vector<float> recurrent_to_input_weights = {
- -0.0063535, -0.2042388, 0.31454784, -0.35746509, 0.28902304, 0.08183324,
- -0.16555229, 0.02286911, -0.13566875, 0.03034258, 0.48091322, -0.12528998,
- 0.24077177, -0.51332325, -0.33502164, 0.10629296};
-
- std::vector<float> recurrent_to_forget_weights = {
- -0.48684245, -0.06655136, 0.42224967, 0.2112639, 0.27654213, 0.20864892,
- -0.07646349, 0.45877004, 0.00141793, -0.14609534, 0.36447752, 0.09196436,
- 0.28053468, 0.01560611, -0.20127171, -0.01140004};
-
- std::vector<float> recurrent_to_cell_weights = {
- -0.3407414, 0.24443203, -0.2078532, 0.26320225, 0.05695659, -0.00123841,
- -0.4744786, -0.35869038, -0.06418842, -0.13502428, -0.501764, 0.22830659,
- -0.46367589, 0.26016325, -0.03894562, -0.16368064};
-
- std::vector<float> recurrent_to_output_weights = {
- 0.43385774, -0.17194885, 0.2718237, 0.09215671, 0.24107647, -0.39835793,
- 0.18212086, 0.01301402, 0.48572797, -0.50656658, 0.20047462, -0.20607421,
- -0.51818722, -0.15390486, 0.0468148, 0.39922136};
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- Shape input_to_input_weights_shape{n_cell, n_input};
- Shape input_to_cell_weights_shape{n_cell, n_input};
- Shape input_to_forget_weights_shape{n_cell, n_input};
- Shape input_to_output_weights_shape{n_cell, n_input};
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
- Shape input_gate_bias_shape{n_cell};
- Shape forget_gate_bias_shape{n_cell};
- Shape cell_gate_bias_shape{n_cell};
- Shape output_gate_bias_shape{n_cell};
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
- Shape recurrent_to_input_weights_shape{n_cell, n_output};
- Shape recurrent_to_cell_weights_shape{n_cell, n_output};
- Shape recurrent_to_forget_weights_shape{n_cell, n_output};
- Shape recurrent_to_output_weights_shape{n_cell, n_output};
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
- Tensor input_to_input_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- input_to_input_weights_shape, input_to_input_weights, _memory_manager.get());
- Tensor input_to_cell_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- input_to_cell_weights_shape, input_to_cell_weights, _memory_manager.get());
- Tensor input_to_forget_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- input_to_forget_weights_shape, input_to_forget_weights, _memory_manager.get());
- Tensor input_to_output_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- input_to_output_weights_shape, input_to_output_weights, _memory_manager.get());
+ runtime_module.execute();
- Tensor input_gate_bias_tensor = makeInputTensor<DataType::FLOAT32>(
- input_gate_bias_shape, input_gate_bias, _memory_manager.get());
- Tensor forget_gate_bias_tensor = makeInputTensor<DataType::FLOAT32>(
- forget_gate_bias_shape, forget_gate_bias, _memory_manager.get());
- Tensor cell_gate_bias_tensor =
- makeInputTensor<DataType::FLOAT32>(cell_gate_bias_shape, cell_gate_bias, _memory_manager.get());
- Tensor output_gate_bias_tensor = makeInputTensor<DataType::FLOAT32>(
- output_gate_bias_shape, output_gate_bias, _memory_manager.get());
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
- Tensor recurrent_to_input_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- recurrent_to_input_weights_shape, recurrent_to_input_weights, _memory_manager.get());
- Tensor recurrent_to_cell_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- recurrent_to_cell_weights_shape, recurrent_to_cell_weights, _memory_manager.get());
- Tensor recurrent_to_forget_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- recurrent_to_forget_weights_shape, recurrent_to_forget_weights, _memory_manager.get());
- Tensor recurrent_to_output_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- recurrent_to_output_weights_shape, recurrent_to_output_weights, _memory_manager.get());
-
- std::vector<float> input_data{2., 3., 3., 4., 1., 1.};
- Shape input_shape{sequence_length, n_batch, n_input};
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
-
- Shape output_state_shape{n_batch, n_output};
- Tensor output_state_tensor = makeOutputTensor(DataType::FLOAT32);
- output_state_tensor.resize(output_state_shape);
-
- Shape cell_state_shape{n_batch, n_cell};
- Tensor cell_state_tensor = makeOutputTensor(DataType::FLOAT32);
- cell_state_tensor.resize(cell_state_shape);
-
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- Tensor scratchpad_1(DataType::FLOAT32, Shape({}), {}, "");
- Tensor scratchpad_2(DataType::FLOAT32, Shape({}), {}, "");
- Tensor scratchpad_3(DataType::FLOAT32, Shape({}), {}, "");
-
- UnidirectionalSequenceLSTMParams params{};
- params.activation = Activation::TANH;
- params.cell_clip = 0.0;
- params.proj_clip = 0.0;
- params.time_major = true;
- params.asymmetric_quantize_inputs = false;
-
- UnidirectionalSequenceLSTM kernel(
- &input_tensor, &input_to_input_weights_tensor, &input_to_forget_weights_tensor,
- &input_to_cell_weights_tensor, &input_to_output_weights_tensor,
- &recurrent_to_input_weights_tensor, &recurrent_to_forget_weights_tensor,
- &recurrent_to_cell_weights_tensor, &recurrent_to_output_weights_tensor, nullptr, nullptr,
- nullptr, &input_gate_bias_tensor, &forget_gate_bias_tensor, &cell_gate_bias_tensor,
- &output_gate_bias_tensor, nullptr, nullptr, &output_state_tensor, &cell_state_tensor, nullptr,
- nullptr, nullptr, nullptr, &output_tensor, &scratchpad_1, &scratchpad_2, &scratchpad_3, params);
-
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- _memory_manager->allocate_memory(output_state_tensor);
- _memory_manager->allocate_memory(cell_state_tensor);
- _memory_manager->allocate_memory(scratchpad_1);
- _memory_manager->allocate_memory(scratchpad_2);
- _memory_manager->allocate_memory(scratchpad_3);
- kernel.execute();
-
- std::vector<float> ref_output_data{-0.02973187, 0.1229473, 0.20885126, -0.15358765,
- -0.03716109, 0.12507336, 0.41193449, -0.20860538,
- -0.15053082, 0.09120187, 0.24278517, -0.12222792};
-
- std::vector<float> ref_output_shape{sequence_length, n_batch, n_output};
- const float tolerance = 1e-5;
- EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data, tolerance));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST_F(UnidirectionalSequenceLSTMTest, FloatTest_batch)
+TEST_F(UnidirectionalLSTMTest, Float_P)
{
- const int32_t n_batch = 1;
- const int32_t n_input = 2;
- const int32_t n_cell = 4;
- const int32_t n_output = 4;
- const int32_t sequence_length = 3;
-
- std::vector<float> input_to_input_weights = {-0.45018822, -0.02338299, -0.0870589, -0.34550029,
- 0.04266912, -0.15680569, -0.34856534, 0.43890524};
-
- std::vector<float> input_to_cell_weights = {-0.50013041, 0.1370284, 0.11810488, 0.2013163,
- -0.20583314, 0.44344562, 0.22077113, -0.29909778};
-
- std::vector<float> input_to_forget_weights = {0.09701663, 0.20334584, -0.50592935, -0.31343272,
- -0.40032279, 0.44781327, 0.01387155, -0.35593212};
-
- std::vector<float> input_to_output_weights = {-0.25065863, -0.28290087, 0.04613829, 0.40525138,
- 0.44272184, 0.03897077, -0.1556896, 0.19487578};
-
- std::vector<float> input_gate_bias = {0., 0., 0., 0.};
- std::vector<float> forget_gate_bias = {1., 1., 1., 1.};
- std::vector<float> cell_gate_bias = {0., 0., 0., 0.};
- std::vector<float> output_gate_bias = {0., 0., 0., 0.};
-
- std::vector<float> recurrent_to_input_weights = {
- -0.0063535, -0.2042388, 0.31454784, -0.35746509, 0.28902304, 0.08183324,
- -0.16555229, 0.02286911, -0.13566875, 0.03034258, 0.48091322, -0.12528998,
- 0.24077177, -0.51332325, -0.33502164, 0.10629296};
-
- std::vector<float> recurrent_to_forget_weights = {
- -0.48684245, -0.06655136, 0.42224967, 0.2112639, 0.27654213, 0.20864892,
- -0.07646349, 0.45877004, 0.00141793, -0.14609534, 0.36447752, 0.09196436,
- 0.28053468, 0.01560611, -0.20127171, -0.01140004};
-
- std::vector<float> recurrent_to_cell_weights = {
- -0.3407414, 0.24443203, -0.2078532, 0.26320225, 0.05695659, -0.00123841,
- -0.4744786, -0.35869038, -0.06418842, -0.13502428, -0.501764, 0.22830659,
- -0.46367589, 0.26016325, -0.03894562, -0.16368064};
-
- std::vector<float> recurrent_to_output_weights = {
- 0.43385774, -0.17194885, 0.2718237, 0.09215671, 0.24107647, -0.39835793,
- 0.18212086, 0.01301402, 0.48572797, -0.50656658, 0.20047462, -0.20607421,
- -0.51818722, -0.15390486, 0.0468148, 0.39922136};
-
- Shape input_to_input_weights_shape{n_cell, n_input};
- Shape input_to_cell_weights_shape{n_cell, n_input};
- Shape input_to_forget_weights_shape{n_cell, n_input};
- Shape input_to_output_weights_shape{n_cell, n_input};
-
- Shape input_gate_bias_shape{n_cell};
- Shape forget_gate_bias_shape{n_cell};
- Shape cell_gate_bias_shape{n_cell};
- Shape output_gate_bias_shape{n_cell};
-
- Shape recurrent_to_input_weights_shape{n_cell, n_output};
- Shape recurrent_to_cell_weights_shape{n_cell, n_output};
- Shape recurrent_to_forget_weights_shape{n_cell, n_output};
- Shape recurrent_to_output_weights_shape{n_cell, n_output};
-
- Tensor input_to_input_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- input_to_input_weights_shape, input_to_input_weights, _memory_manager.get());
- Tensor input_to_cell_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- input_to_cell_weights_shape, input_to_cell_weights, _memory_manager.get());
- Tensor input_to_forget_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- input_to_forget_weights_shape, input_to_forget_weights, _memory_manager.get());
- Tensor input_to_output_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- input_to_output_weights_shape, input_to_output_weights, _memory_manager.get());
-
- Tensor input_gate_bias_tensor = makeInputTensor<DataType::FLOAT32>(
- input_gate_bias_shape, input_gate_bias, _memory_manager.get());
- Tensor forget_gate_bias_tensor = makeInputTensor<DataType::FLOAT32>(
- forget_gate_bias_shape, forget_gate_bias, _memory_manager.get());
- Tensor cell_gate_bias_tensor =
- makeInputTensor<DataType::FLOAT32>(cell_gate_bias_shape, cell_gate_bias, _memory_manager.get());
- Tensor output_gate_bias_tensor = makeInputTensor<DataType::FLOAT32>(
- output_gate_bias_shape, output_gate_bias, _memory_manager.get());
-
- Tensor recurrent_to_input_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- recurrent_to_input_weights_shape, recurrent_to_input_weights, _memory_manager.get());
- Tensor recurrent_to_cell_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- recurrent_to_cell_weights_shape, recurrent_to_cell_weights, _memory_manager.get());
- Tensor recurrent_to_forget_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- recurrent_to_forget_weights_shape, recurrent_to_forget_weights, _memory_manager.get());
- Tensor recurrent_to_output_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- recurrent_to_output_weights_shape, recurrent_to_output_weights, _memory_manager.get());
-
- std::vector<float> input_data{2., 3., 3., 4., 1., 1.};
- Shape input_shape{n_batch, sequence_length, n_input};
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
-
- Shape output_state_shape{n_batch, n_output};
- Tensor output_state_tensor = makeOutputTensor(DataType::FLOAT32);
- output_state_tensor.resize(output_state_shape);
-
- Shape cell_state_shape{n_batch, n_cell};
- Tensor cell_state_tensor = makeOutputTensor(DataType::FLOAT32);
- cell_state_tensor.resize(cell_state_shape);
-
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- Tensor scratchpad_1(DataType::FLOAT32, Shape({}), {}, "");
-
- UnidirectionalSequenceLSTMParams params{};
- params.activation = Activation::TANH;
- params.cell_clip = 0.0;
- params.proj_clip = 0.0;
- params.time_major = false;
- params.asymmetric_quantize_inputs = false;
-
- UnidirectionalSequenceLSTM kernel(
- &input_tensor, &input_to_input_weights_tensor, &input_to_forget_weights_tensor,
- &input_to_cell_weights_tensor, &input_to_output_weights_tensor,
- &recurrent_to_input_weights_tensor, &recurrent_to_forget_weights_tensor,
- &recurrent_to_cell_weights_tensor, &recurrent_to_output_weights_tensor, nullptr, nullptr,
- nullptr, &input_gate_bias_tensor, &forget_gate_bias_tensor, &cell_gate_bias_tensor,
- &output_gate_bias_tensor, nullptr, nullptr, &output_state_tensor, &cell_state_tensor, nullptr,
- nullptr, nullptr, nullptr, &output_tensor, &output_state_tensor, &cell_state_tensor,
- &scratchpad_1, params);
-
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- _memory_manager->allocate_memory(output_state_tensor);
- _memory_manager->allocate_memory(cell_state_tensor);
- _memory_manager->allocate_memory(scratchpad_1);
- kernel.execute();
-
- std::vector<float> ref_output_data{-0.02973187, 0.1229473, 0.20885126, -0.15358765,
- -0.03716109, 0.12507336, 0.41193449, -0.20860538,
- -0.15053082, 0.09120187, 0.24278517, -0.12222792};
-
- std::vector<float> ref_output_shape{n_batch, sequence_length, n_output};
- const float tolerance = 1e-5;
- EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data, tolerance));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+ test_kernel::TestDataFloatUnidirectionalLSTM test_data_kernel;
+ std::vector<float> output_data_vector = checkUnidirectionalSequenceLSTMKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+ test_data_kernel.get_output_data_by_index(0), 0.0001f));
}
-TEST_F(UnidirectionalSequenceLSTMTest, FloatTest_simple)
+TEST_F(UnidirectionalLSTMTest, Int8_P)
{
- const int32_t n_batch = 1;
- const int32_t n_input = 1;
- const int32_t n_cell = 1;
- const int32_t n_output = 1;
- const int32_t sequence_length = 1;
-
- std::vector<float> input_to_input_weights = {0.329067};
- std::vector<float> input_to_forget_weights = {0.308059};
- std::vector<float> input_to_cell_weights = {0.152916};
- std::vector<float> input_to_output_weights = {-0.476033};
-
- std::vector<float> input_gate_bias = {0.};
- std::vector<float> forget_gate_bias = {1.};
- std::vector<float> cell_gate_bias = {0.};
- std::vector<float> output_gate_bias = {0.};
-
- std::vector<float> recurrent_to_input_weights = {0.207806};
- std::vector<float> recurrent_to_forget_weights = {0.028718};
- std::vector<float> recurrent_to_cell_weights = {-0.182756};
- std::vector<float> recurrent_to_output_weights = {-0.960517};
-
- Shape input_to_input_weights_shape{n_cell, n_input};
- Shape input_to_cell_weights_shape{n_cell, n_input};
- Shape input_to_forget_weights_shape{n_cell, n_input};
- Shape input_to_output_weights_shape{n_cell, n_input};
-
- Shape input_gate_bias_shape{n_cell};
- Shape forget_gate_bias_shape{n_cell};
- Shape cell_gate_bias_shape{n_cell};
- Shape output_gate_bias_shape{n_cell};
-
- Shape recurrent_to_input_weights_shape{n_cell, n_output};
- Shape recurrent_to_cell_weights_shape{n_cell, n_output};
- Shape recurrent_to_forget_weights_shape{n_cell, n_output};
- Shape recurrent_to_output_weights_shape{n_cell, n_output};
-
- Tensor input_to_input_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- input_to_input_weights_shape, input_to_input_weights, _memory_manager.get());
- Tensor input_to_cell_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- input_to_cell_weights_shape, input_to_cell_weights, _memory_manager.get());
- Tensor input_to_forget_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- input_to_forget_weights_shape, input_to_forget_weights, _memory_manager.get());
- Tensor input_to_output_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- input_to_output_weights_shape, input_to_output_weights, _memory_manager.get());
-
- Tensor input_gate_bias_tensor = makeInputTensor<DataType::FLOAT32>(
- input_gate_bias_shape, input_gate_bias, _memory_manager.get());
- Tensor forget_gate_bias_tensor = makeInputTensor<DataType::FLOAT32>(
- forget_gate_bias_shape, forget_gate_bias, _memory_manager.get());
- Tensor cell_gate_bias_tensor =
- makeInputTensor<DataType::FLOAT32>(cell_gate_bias_shape, cell_gate_bias, _memory_manager.get());
- Tensor output_gate_bias_tensor = makeInputTensor<DataType::FLOAT32>(
- output_gate_bias_shape, output_gate_bias, _memory_manager.get());
-
- Tensor recurrent_to_input_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- recurrent_to_input_weights_shape, recurrent_to_input_weights, _memory_manager.get());
- Tensor recurrent_to_cell_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- recurrent_to_cell_weights_shape, recurrent_to_cell_weights, _memory_manager.get());
- Tensor recurrent_to_forget_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- recurrent_to_forget_weights_shape, recurrent_to_forget_weights, _memory_manager.get());
- Tensor recurrent_to_output_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- recurrent_to_output_weights_shape, recurrent_to_output_weights, _memory_manager.get());
-
- std::vector<float> input_data{0.03653763};
- Shape input_shape{n_batch, sequence_length, n_input};
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
-
- Shape output_state_shape{n_batch, n_output};
- Tensor output_state_tensor = makeOutputTensor(DataType::FLOAT32);
- output_state_tensor.resize(output_state_shape);
-
- Shape cell_state_shape{n_batch, n_cell};
- Tensor cell_state_tensor = makeOutputTensor(DataType::FLOAT32);
- cell_state_tensor.resize(cell_state_shape);
-
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
- Tensor scratchpad_1(DataType::FLOAT32, Shape({}), {}, "");
-
- UnidirectionalSequenceLSTMParams params{};
- params.activation = Activation::TANH;
- params.cell_clip = 10.0;
- params.proj_clip = 0.0;
- params.time_major = false;
- params.asymmetric_quantize_inputs = false;
-
- UnidirectionalSequenceLSTM kernel(
- &input_tensor, &input_to_input_weights_tensor, &input_to_forget_weights_tensor,
- &input_to_cell_weights_tensor, &input_to_output_weights_tensor,
- &recurrent_to_input_weights_tensor, &recurrent_to_forget_weights_tensor,
- &recurrent_to_cell_weights_tensor, &recurrent_to_output_weights_tensor, nullptr, nullptr,
- nullptr, &input_gate_bias_tensor, &forget_gate_bias_tensor, &cell_gate_bias_tensor,
- &output_gate_bias_tensor, nullptr, nullptr, &output_state_tensor, &cell_state_tensor, nullptr,
- nullptr, nullptr, nullptr, &output_tensor, &output_state_tensor, &cell_state_tensor,
- &scratchpad_1, params);
-
- kernel.configure();
- _memory_manager->allocate_memory(output_tensor);
- _memory_manager->allocate_memory(output_state_tensor);
- _memory_manager->allocate_memory(cell_state_tensor);
- _memory_manager->allocate_memory(scratchpad_1);
- kernel.execute();
-
- std::vector<float> ref_output_data{0.00139296};
- std::vector<float> ref_output_shape{n_batch, sequence_length, n_output};
- const float tolerance = 1e-5;
- auto aa = extractTensorData<float>(output_tensor);
- EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data, tolerance));
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+ test_kernel::TestDataInt8UnidirectionalLSTM test_data_kernel;
+ std::vector<int8_t> output_data_vector = checkUnidirectionalSequenceLSTMKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
}
-TEST_F(UnidirectionalSequenceLSTMTest, Unsupported_Type_Configure_NEG)
-{
- const int32_t n_batch = 1;
- const int32_t n_input = 2;
- const int32_t n_cell = 4;
- const int32_t n_output = 4;
- const int32_t sequence_length = 3;
-
- std::vector<int8_t> input_data{2, 3, 3, 4, 1, 1}; // int8 is not support as of now
- Shape input_shape{sequence_length, n_batch, n_input};
- Tensor input_tensor =
- makeInputTensor<DataType::S8>(input_shape, input_data, _memory_manager.get());
-
- std::vector<float> input_to_input_weights = {-0.45018822, -0.02338299, -0.0870589, -0.34550029,
- 0.04266912, -0.15680569, -0.34856534, 0.43890524};
- Shape input_to_input_weights_shape{n_cell, n_input};
- Tensor input_to_input_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- input_to_input_weights_shape, input_to_input_weights, _memory_manager.get());
-
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
- Tensor scratchpad_1(DataType::FLOAT32, Shape({}), {}, "");
- Tensor scratchpad_2(DataType::FLOAT32, Shape({}), {}, "");
- Tensor scratchpad_3(DataType::FLOAT32, Shape({}), {}, "");
-
- UnidirectionalSequenceLSTMParams params{};
- params.activation = Activation::TANH;
- params.cell_clip = 0.0;
- params.proj_clip = 0.0;
- params.time_major = true;
- params.asymmetric_quantize_inputs = false;
-
- UnidirectionalSequenceLSTM kernel(
- &input_tensor, &input_to_input_weights_tensor, &input_to_input_weights_tensor,
- &input_to_input_weights_tensor, &input_to_input_weights_tensor, &input_to_input_weights_tensor,
- &input_to_input_weights_tensor, &input_to_input_weights_tensor, &input_to_input_weights_tensor,
- nullptr, nullptr, nullptr, &input_to_input_weights_tensor, &input_to_input_weights_tensor,
- &input_to_input_weights_tensor, &input_to_input_weights_tensor, nullptr, nullptr,
- &input_to_input_weights_tensor, &input_to_input_weights_tensor, nullptr, nullptr, nullptr,
- nullptr, &output_tensor, &scratchpad_1, &scratchpad_2, &scratchpad_3, params);
-
- EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(UnidirectionalSequenceLSTMTest, Invalid_Input_Shape_NEG)
-{
- const int32_t n_batch = 1;
- const int32_t n_input = 2;
- const int32_t n_cell = 4;
- const int32_t n_output = 4;
- const int32_t sequence_length = 3;
-
- std::vector<float> input_data{2., 3., 3., 4., 1., 1.};
- Shape input_shape{sequence_length, n_input}; // this is wrong
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
-
- std::vector<float> input_to_input_weights = {-0.45018822, -0.02338299, -0.0870589, -0.34550029,
- 0.04266912, -0.15680569, -0.34856534, 0.43890524};
- Shape input_to_input_weights_shape{n_cell, n_input};
- Tensor input_to_input_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- input_to_input_weights_shape, input_to_input_weights, _memory_manager.get());
-
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
- Tensor scratchpad_1(DataType::FLOAT32, Shape({}), {}, "");
- Tensor scratchpad_2(DataType::FLOAT32, Shape({}), {}, "");
- Tensor scratchpad_3(DataType::FLOAT32, Shape({}), {}, "");
-
- UnidirectionalSequenceLSTMParams params{};
- params.activation = Activation::TANH;
- params.cell_clip = 0.0;
- params.proj_clip = 0.0;
- params.time_major = true;
- params.asymmetric_quantize_inputs = false;
-
- UnidirectionalSequenceLSTM kernel(
- &input_tensor, &input_to_input_weights_tensor, &input_to_input_weights_tensor,
- &input_to_input_weights_tensor, &input_to_input_weights_tensor, &input_to_input_weights_tensor,
- &input_to_input_weights_tensor, &input_to_input_weights_tensor, &input_to_input_weights_tensor,
- nullptr, nullptr, nullptr, &input_to_input_weights_tensor, &input_to_input_weights_tensor,
- &input_to_input_weights_tensor, &input_to_input_weights_tensor, nullptr, nullptr,
- &input_to_input_weights_tensor, &input_to_input_weights_tensor, nullptr, nullptr, nullptr,
- nullptr, &output_tensor, &scratchpad_1, &scratchpad_2, &scratchpad_3, params);
-
- EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(UnidirectionalSequenceLSTMTest, Invalid_Input_Shape_2_NEG)
-{
- const int32_t n_batch = 1;
- const int32_t n_input = 2;
- const int32_t n_cell = 4;
- const int32_t n_output = 4;
- const int32_t sequence_length = 3;
-
- std::vector<float> input_data{2., 3., 3., 4., 1., 1.};
- Shape input_shape{sequence_length, n_batch, n_input};
- Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
-
- std::vector<float> input_to_input_weights = {-0.45018822, -0.02338299, -0.0870589, -0.34550029,
- 0.04266912, -0.15680569, -0.34856534, 0.43890524};
- Shape input_to_input_weights_shape{n_cell, n_input};
- Tensor input_to_input_weights_tensor = makeInputTensor<DataType::FLOAT32>(
- input_to_input_weights_shape, input_to_input_weights, _memory_manager.get());
-
- Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
- Tensor scratchpad_1(DataType::FLOAT32, Shape({}), {}, "");
- Tensor scratchpad_2(DataType::FLOAT32, Shape({}), {}, "");
- Tensor scratchpad_3(DataType::FLOAT32, Shape({}), {}, "");
-
- UnidirectionalSequenceLSTMParams params{};
- params.activation = Activation::TANH;
- params.cell_clip = 0.0;
- params.proj_clip = 0.0;
- params.time_major = true;
- params.asymmetric_quantize_inputs = false;
-
- // NOTE provide wrong shaped inputs
- UnidirectionalSequenceLSTM kernel(
- &input_tensor, &input_to_input_weights_tensor, &input_to_input_weights_tensor,
- &input_to_input_weights_tensor, &input_to_input_weights_tensor, &input_to_input_weights_tensor,
- &input_to_input_weights_tensor, &input_to_input_weights_tensor, &input_to_input_weights_tensor,
- nullptr, nullptr, nullptr, &input_to_input_weights_tensor, &input_to_input_weights_tensor,
- &input_to_input_weights_tensor, &input_to_input_weights_tensor, nullptr, nullptr,
- &input_to_input_weights_tensor, &input_to_input_weights_tensor, nullptr, nullptr, nullptr,
- nullptr, &output_tensor, &scratchpad_1, &scratchpad_2, &scratchpad_3, params);
-
- EXPECT_ANY_THROW(kernel.configure());
-}
+// TODO: add negative tests?
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Unpack.cpp b/onert-micro/luci-interpreter/src/kernels/Unpack.cpp
index cc8cf3a89..80f4d1f28 100644
--- a/onert-micro/luci-interpreter/src/kernels/Unpack.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Unpack.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Unpack.h b/onert-micro/luci-interpreter/src/kernels/Unpack.h
index 4580491ff..f4a44ecad 100644
--- a/onert-micro/luci-interpreter/src/kernels/Unpack.h
+++ b/onert-micro/luci-interpreter/src/kernels/Unpack.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/onert-micro/luci-interpreter/src/kernels/Utils.cpp b/onert-micro/luci-interpreter/src/kernels/Utils.cpp
index 0810b82dd..35ab82180 100644
--- a/onert-micro/luci-interpreter/src/kernels/Utils.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/Utils.cpp
@@ -26,6 +26,26 @@ namespace luci_interpreter
namespace kernels
{
+luci_interpreter::RuntimeShape getTensorRuntimeShape(const circle::Tensor *circle_tensor,
+ BaseRuntimeGraph *runtime_graph)
+{
+ luci_interpreter::RuntimeShape input_shape = getTensorShape(circle_tensor);
+
+#ifndef DIS_DYN_SHAPES
+ auto *dynamic_shape_vector = runtime_graph->getDynamicShapeTensor(circle_tensor);
+ if (dynamic_shape_vector != nullptr)
+ {
+ input_shape.resize(dynamic_shape_vector->dimensionsCount());
+
+ for (int n = 0; n < dynamic_shape_vector->dimensionsCount(); ++n)
+ {
+ input_shape.setDim(n, dynamic_shape_vector->dims(n));
+ }
+ }
+#endif // DIS_DYN_SHAPES
+ return input_shape;
+}
+
template <typename T>
void calculateActivationRange(Activation activation, T *activation_min, T *activation_max)
{
@@ -74,6 +94,26 @@ template void calculateActivationRange(Activation activation, int64_t *activatio
int64_t *activation_max);
#ifndef DIS_QUANT
+bool checkedLog2(const float x, int *log2_result)
+{
+ const float x_log2 = std::log(x) * (1.0f / std::log(2.0f));
+ const float x_log2_rounded = std::round(x_log2);
+ const float x_log2_fracpart = x_log2 - x_log2_rounded;
+
+ *log2_result = static_cast<int>(x_log2_rounded);
+ return std::abs(x_log2_fracpart) < 1e-3f;
+}
+
+int calculateInputRadius(int input_integer_bits, int input_left_shift, int total_signed_bits)
+{
+ const double max_input_rescaled = 1.0 * ((1 << input_integer_bits) - 1) *
+ (1LL << (total_signed_bits - input_integer_bits)) /
+ (1LL << input_left_shift);
+ // Tighten bound using floor. Suppose that we could use the exact value.
+ // After scaling the difference, the result would be at the maximum. Thus we
+ // must ensure that our value has lower magnitude.
+ return static_cast<int>(std::floor(max_input_rescaled));
+}
static void calculateActivationRangeQuantizedImpl(Activation activation, int32_t qmin, int32_t qmax,
int32_t zero_point, float scale,
@@ -206,13 +246,13 @@ void quantizeMultiplierSmallerThanOneExp(double double_multiplier, int32_t *quan
}
#endif
-tflite::RuntimeShape calculateShapeForBroadcast(const circle::Tensor *input1,
- const circle::Tensor *input2)
+luci_interpreter::RuntimeShape calculateShapeForBroadcast(const circle::Tensor *input1,
+ const circle::Tensor *input2)
{
const int num_input1_dims = Tensor::num_dims(input1);
const int num_input2_dims = Tensor::num_dims(input2);
const int num_out_dims = std::max(num_input1_dims, num_input2_dims);
- tflite::RuntimeShape output_shape(num_out_dims);
+ luci_interpreter::RuntimeShape output_shape(num_out_dims);
for (int i = 0; i < num_out_dims; ++i)
{
@@ -225,7 +265,7 @@ tflite::RuntimeShape calculateShapeForBroadcast(const circle::Tensor *input1,
bool can_broadcast = input1_dim == 1 || input2_dim == 1;
LUCI_INTERPRETER_CHECK(!need_broadcast || can_broadcast);
- output_shape.SetDim(num_out_dims - i - 1, std::max(input1_dim, input2_dim));
+ output_shape.setDim(num_out_dims - i - 1, std::max(input1_dim, input2_dim));
}
return output_shape;
diff --git a/onert-micro/luci-interpreter/src/kernels/Utils.h b/onert-micro/luci-interpreter/src/kernels/Utils.h
index 8d3cd69c4..a01d72dfa 100644
--- a/onert-micro/luci-interpreter/src/kernels/Utils.h
+++ b/onert-micro/luci-interpreter/src/kernels/Utils.h
@@ -19,11 +19,13 @@
#define LUCI_INTERPRETER_KERNELS_UTILS_H
#include "luci_interpreter/core/Tensor.h"
-
-#include <tensorflow/lite/kernels/internal/types.h>
+#include "Builders.h"
+#include "Params.h"
#include <cassert>
#include <cstdint>
+#include <cmath>
+
namespace luci_interpreter
{
namespace kernels
@@ -62,8 +64,10 @@ inline int32_t computeOutputSize(Padding padding, int32_t image_size, int32_t fi
switch (padding)
{
case Padding::SAME:
+ assert(stride != 0);
return (image_size + stride - 1) / stride;
case Padding::VALID:
+ assert(stride != 0);
return (image_size + stride - effective_filter_size) / stride;
default:
assert(false);
@@ -83,8 +87,8 @@ inline int32_t calcOffset(const circle::Tensor *tensor, int32_t d0, int32_t d1,
template <typename T>
void calculateActivationRange(Activation activation, T *activation_min, T *activation_max);
-tflite::RuntimeShape calculateShapeForBroadcast(const circle::Tensor *input1,
- const circle::Tensor *input2);
+luci_interpreter::RuntimeShape calculateShapeForBroadcast(const circle::Tensor *input1,
+ const circle::Tensor *input2);
// Helper wrapper to hide broadcast logic
template <typename T> class BroadcastableWrapper
@@ -99,29 +103,71 @@ private:
int _stride;
};
-inline tflite::RuntimeShape getTensorShape(const circle::Tensor *tensor)
+inline luci_interpreter::RuntimeShape getTensorShape(const circle::Tensor *tensor)
{
if (tensor == nullptr)
- return tflite::RuntimeShape();
+ return luci_interpreter::RuntimeShape();
+
+ auto const tensor_shape = Tensor::tensor_shape(tensor);
- tflite::RuntimeShape runtime_shape(Tensor::num_dims(tensor));
- for (int i = 0; i < Tensor::num_dims(tensor); ++i)
+ luci_interpreter::RuntimeShape runtime_shape(tensor_shape.size());
+ for (int i = 0; i < tensor_shape.size(); ++i)
{
- runtime_shape.SetDim(i, Tensor::dim(tensor, i));
+ runtime_shape.setDim(i, tensor_shape[i]);
}
return runtime_shape;
}
+inline void getTensorDims(const circle::Tensor *tensor, BaseRuntimeGraph *runtime_graph,
+ int32_t *dims)
+{
+ if (tensor == nullptr)
+ {
+ dims = nullptr;
+ return;
+ }
+
+#ifndef DIS_DYN_SHAPES
+ auto *dynamic_shape_vector = runtime_graph->getDynamicShapeTensor(tensor);
+ if (dynamic_shape_vector != nullptr)
+ {
+ for (int n = 0; n < dynamic_shape_vector->dimensionsCount(); ++n)
+ {
+ dims[n] = dynamic_shape_vector->dims(n);
+ }
+ }
+ else
+ {
+ auto const tensor_shape = Tensor::tensor_shape(tensor);
+ assert(tensor_shape.size() <= kMaxSmallSize);
+ for (int i = 0; i < tensor_shape.size(); ++i)
+ {
+ dims[i] = tensor_shape[i];
+ }
+ }
+#else
+ auto const tensor_shape = Tensor::tensor_shape(tensor);
+ assert(tensor_shape.size() <= kMaxSmallSize);
+ for (int i = 0; i < tensor_shape.size(); ++i)
+ {
+ dims[i] = tensor_shape[i];
+ }
+#endif // DIS_DYN_SHAPES
+}
+
template <typename T> const T *getTensorData(const uint8_t *tensor_data)
{
return tensor_data != nullptr ? reinterpret_cast<const T *>(tensor_data) : nullptr;
}
-template <typename T> T *getTensorData(uint8_t *tensor_data)
+template <typename T> inline T *getTensorData(uint8_t *tensor_data)
{
return tensor_data != nullptr ? reinterpret_cast<T *>(tensor_data) : nullptr;
}
+luci_interpreter::RuntimeShape getTensorRuntimeShape(const circle::Tensor *circle_tensor,
+ BaseRuntimeGraph *runtime_graph);
+
// A list of tensors in a format that can be used by kernels like split and
// concatenation.
template <typename T, bool is_const> class VectorOfTensors
@@ -148,7 +194,7 @@ public:
// Taking the pointer from inside a std::vector is only OK if the vector is
// never modified, so we populate all_shape in the previous loop and then we
// are free to grab iterators here.
- for (tflite::RuntimeShape &shape : all_shape_)
+ for (luci_interpreter::RuntimeShape &shape : all_shape_)
{
all_shape_ptr_.push_back(&shape);
}
@@ -163,21 +209,14 @@ public:
// example:
// const RuntimeShape* const* d = v.dims();
// dims[1] are the dimensions of the second tensor in the list.
- const tflite::RuntimeShape *const *shapes() const { return all_shape_ptr_.data(); }
+ const luci_interpreter::RuntimeShape *const *shapes() const { return all_shape_ptr_.data(); }
private:
std::vector<ElementT *> all_data_;
- std::vector<tflite::RuntimeShape> all_shape_;
- std::vector<tflite::RuntimeShape *> all_shape_ptr_;
+ std::vector<luci_interpreter::RuntimeShape> all_shape_;
+ std::vector<luci_interpreter::RuntimeShape *> all_shape_ptr_;
};
-#ifndef DIS_QUANT
-void calculateActivationRangeQuantized(Activation activation, const circle::Tensor *output,
- int32_t *activation_min, int32_t *activation_max);
-void calculateActivationRangeQuantized(Activation activation, int32_t output_zero_point,
- float output_scale, DataType data_type,
- int32_t *activation_min, int32_t *activation_max);
-
template <typename T> constexpr bool one_of_types() { return false; }
// Checks if T is equal to one of {U,Other} types
@@ -189,27 +228,17 @@ template <typename T, typename U, typename... Other> constexpr bool one_of_types
void matrixScalarMultiplyAccumulate(const int8_t *matrix, int32_t scalar, int32_t n_row,
int32_t n_col, int32_t *output);
-/**
- * Fills activation min and max parameters depending on given data type and activation
- *
- * T is a template parameter, so after optimization this code left with only required if case
- *
- * @tparam T data type of arithmetic operation output tensor
- * @param params tflite params to fill
- * @param activation luci_interpreter::Activation of arithmetic operation
- */
-template <typename T>
-void fillArithmeticActivationRange(tflite::ArithmeticParams &p, Activation act)
-{
- static_assert(one_of_types<T, float, int32_t, int64_t>(), "Unsupported dtype");
+#ifndef DIS_QUANT
+bool checkedLog2(const float x, int *log2_result);
- if (std::is_same<T, float>::value)
- calculateActivationRange(act, &p.float_activation_min, &p.float_activation_max);
- if (std::is_same<T, int32_t>::value)
- calculateActivationRange(act, &p.quantized_activation_min, &p.quantized_activation_max);
- else
- calculateActivationRange(act, &p.int64_activation_min, &p.int64_activation_max);
-}
+int calculateInputRadius(int input_integer_bits, int input_left_shift, int total_signed_bits);
+
+void calculateActivationRangeQuantized(Activation activation, const circle::Tensor *output,
+ int32_t *activation_min, int32_t *activation_max);
+
+void calculateActivationRangeQuantized(Activation activation, int32_t output_zero_point,
+ float output_scale, DataType data_type,
+ int32_t *activation_min, int32_t *activation_max);
// Decompose a double multiplier into a Q0.31 int32 representation of its
// significand, and shift representation of its exponent.
diff --git a/onert-micro/luci-interpreter/src/kernels/While.cpp b/onert-micro/luci-interpreter/src/kernels/While.cpp
index 153bd1a99..6826c2b26 100644
--- a/onert-micro/luci-interpreter/src/kernels/While.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/While.cpp
@@ -15,102 +15,170 @@
* limitations under the License.
*/
-#include "kernels/While.h"
+#include "Builders.h"
#include "kernels/Utils.h"
#include <cstring>
namespace luci_interpreter
{
-namespace kernels
-{
-namespace
+void configure_kernel_CircleWhile(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
+ auto *main_runtime_graph = runtime_graph;
+
+ auto *runtime_module = runtime_graph->getRuntimeModule();
+
+ const auto *options = cur_op->builtin_options_as_WhileOptions();
+ const auto body_subgraph_index = options->body_subgraph_index();
+ const auto cond_subgraph_index = options->cond_subgraph_index();
+
+ auto *cond_runtime_graph = runtime_module->getRuntimeGraphAt(cond_subgraph_index);
+ auto *body_runtime_graph = runtime_module->getRuntimeGraphAt(body_subgraph_index);
+
+ body_runtime_graph->selectOwnSubgraph();
+ const auto body_input_size = body_runtime_graph->getNumOfInputTensors();
+ const auto body_output_size = body_runtime_graph->getNumOfOutputTensors();
+ LUCI_INTERPRETER_CHECK(body_input_size == cur_op->inputs()->size());
+ LUCI_INTERPRETER_CHECK(body_output_size == cur_op->outputs()->size());
+ LUCI_INTERPRETER_CHECK(body_output_size == cur_op->inputs()->size());
+ body_runtime_graph->invalidate();
+ body_runtime_graph->configure(false);
+
+ cond_runtime_graph->selectOwnSubgraph();
+ const auto cond_input_size = cond_runtime_graph->getNumOfInputTensors();
+ const auto cond_output_size = cond_runtime_graph->getNumOfOutputTensors();
+ LUCI_INTERPRETER_CHECK(cond_input_size == cur_op->inputs()->size());
+ LUCI_INTERPRETER_CHECK(cond_output_size == 1);
+ const circle::Tensor *cond_output_tensor = cond_runtime_graph->getOutputTensorByIndex(0);
+ LUCI_INTERPRETER_CHECK(Tensor::element_type(cond_output_tensor) == DataType::BOOL);
+ cond_runtime_graph->invalidate();
+ cond_runtime_graph->configure(false);
+
+ main_runtime_graph->selectOwnSubgraph();
+}
-void copy(const std::vector<const Tensor *> &src, const std::vector<Tensor *> &dst)
+void execute_kernel_CircleWhile(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
{
- for (size_t i = 0; i < src.size(); ++i)
- {
- LUCI_INTERPRETER_CHECK(dst[i]->element_type() == src[i]->element_type());
- dst[i]->resize(src[i]->shape());
+ auto *main_runtime_graph = runtime_graph;
+ auto *runtime_module = runtime_graph->getRuntimeModule();
- const int32_t num_elements = src[i]->shape().num_elements();
- const std::size_t element_size = getDataTypeSize(src[i]->element_type());
- std::memcpy(dst[i]->data<void>(), src[i]->data<void>(), num_elements * element_size);
- }
-}
+ const auto input_size = cur_op->inputs()->size();
-void copy(const std::vector<Tensor *> &src, const std::vector<Tensor *> &dst)
-{
- std::vector<const Tensor *> const_src;
- for (const auto &t : src)
- const_src.push_back(t);
- copy(const_src, dst);
-}
+ std::vector<uint8_t *> operation_inputs_data(input_size);
+ std::vector<uint8_t *> operation_outputs_data;
-// TODO: Think about how allocate memory for output in main graph
-void configureTensorsAllocations(const std::vector<Tensor *> &tensors, RuntimeGraph *run_graph)
-{
- for (auto tensor : tensors)
- run_graph->configureAllocations(tensor);
-}
+ std::vector<int32_t> input_sizes(input_size);
-} // namespace
+ bool is_inplace = runtime_graph->is_inplace_op(cur_op);
-While::While(std::vector<const Tensor *> inputs, std::vector<Tensor *> outputs,
- RuntimeGraph *cond_graph, RuntimeGraph *body_graph)
- : Kernel(std::move(inputs), std::move(outputs)), _cond_graph(cond_graph), _body_graph(body_graph)
-{
-}
+ for (int32_t i = 0; i < input_size; ++i)
+ {
+ const auto op_input_index = cur_op->inputs()->operator[](i);
+ const auto op_output_index = cur_op->outputs()->operator[](i);
+ assert(op_input_index != -1);
+ assert(op_output_index != -1);
+ const auto input = main_runtime_graph->getCircleTensorByIndex(op_input_index);
+ const auto output = main_runtime_graph->getCircleTensorByIndex(op_output_index);
+
+ input_sizes[i] = Tensor::num_elements(input) * size(Tensor::element_type(input));
+
+ auto *input_data = main_runtime_graph->getDataByTensor(input);
+
+ uint8_t *tensor_data = nullptr;
+ if (is_inplace)
+ {
+ if (input_data == nullptr)
+ {
+ tensor_data = new uint8_t[input_sizes[i]];
+ input_data = main_runtime_graph->getConstDataByTensor(input);
+ assert(input_data != nullptr);
+ std::memcpy(tensor_data, input_data, input_sizes[i]);
+ }
+ else
+ {
+ tensor_data = input_data;
+ }
+ }
+ else
+ {
+ if (input_data == nullptr)
+ input_data = main_runtime_graph->getConstDataByTensor(input);
+ assert(input_data != nullptr);
+ tensor_data = main_runtime_graph->getDataByTensor(output);
+ assert(tensor_data != nullptr);
+ std::memcpy(tensor_data, input_data, input_sizes[i]);
+ }
+ assert(tensor_data != nullptr);
+
+ operation_inputs_data[i] = tensor_data;
+ }
-void While::configure()
-{
- LUCI_INTERPRETER_CHECK(_body_graph->getInputTensors().size() == getInputTensors().size());
- LUCI_INTERPRETER_CHECK(_body_graph->getOutputTensors().size() == getOutputTensors().size());
- LUCI_INTERPRETER_CHECK(_body_graph->getOutputTensors().size() == getInputTensors().size());
+ const auto *options = cur_op->builtin_options_as_WhileOptions();
+ const auto body_subgraph_index = options->body_subgraph_index();
+ const auto cond_subgraph_index = options->cond_subgraph_index();
- LUCI_INTERPRETER_CHECK(_cond_graph->getInputTensors().size() == getInputTensors().size());
+ auto *cond_runtime_graph = runtime_module->getRuntimeGraphAt(cond_subgraph_index);
+ auto *body_runtime_graph = runtime_module->getRuntimeGraphAt(body_subgraph_index);
- const auto &cond_outputs = _cond_graph->getOutputTensors();
- LUCI_INTERPRETER_CHECK(cond_outputs.size() == 1)
- LUCI_INTERPRETER_CHECK(cond_outputs[0]->element_type() == DataType::BOOL);
-}
+ do
+ {
+ cond_runtime_graph->selectOwnSubgraph();
-/**
- * @note Dynamic shape such as {1, 0, 8} may fail in tensor->data()
- */
-void While::execute() const
-{
- const auto &cond_inputs = _cond_graph->getInputTensors();
- const auto &cond_outputs = _cond_graph->getOutputTensors();
+ for (int32_t i = 0; i < input_size; ++i)
+ cond_runtime_graph->configureGraphInput(i, operation_inputs_data[i]);
- configureTensorsAllocations(cond_inputs, _cond_graph);
+ cond_runtime_graph->execute();
- copy(getInputTensors(), cond_inputs);
+ bool cond_value = (cond_runtime_graph->getOutputDataByIndex(0))[0];
+ if (!cond_value)
+ break;
- const auto &body_inputs = _body_graph->getInputTensors();
- const auto &body_outputs = _body_graph->getOutputTensors();
+ body_runtime_graph->selectOwnSubgraph();
+ for (int32_t i = 0; i < input_size; ++i)
+ body_runtime_graph->configureGraphInput(i, operation_inputs_data[i]);
- configureTensorsAllocations(body_inputs, _body_graph);
+ body_runtime_graph->execute();
- while (true)
- {
- _cond_graph->execute();
+ for (int32_t i = 0; i < input_size; ++i)
+ {
+ auto cur_output_body_data = body_runtime_graph->getOutputDataByIndex(i);
+ if (cur_output_body_data == nullptr)
+ continue;
+ std::memcpy(operation_inputs_data[i], cur_output_body_data, input_sizes[i]);
+ }
+ } while (true);
- bool cond_value = cond_outputs[0]->data<bool>()[0];
- if (!cond_value)
- break;
+ cond_runtime_graph->resetOutputTensorsData();
+ cond_runtime_graph->clearTensors();
- copy(cond_inputs, body_inputs);
+ body_runtime_graph->selectOwnSubgraph();
+ body_runtime_graph->resetOutputTensorsData();
+ body_runtime_graph->clearTensors();
- _body_graph->execute();
+ main_runtime_graph->selectOwnSubgraph();
- copy(body_outputs, cond_inputs);
+ if (is_inplace)
+ {
+ for (int32_t i = 0; i < input_size; ++i)
+ {
+ const auto op_input_index = cur_op->inputs()->operator[](i);
+ const auto op_output_index = cur_op->outputs()->operator[](i);
+ assert(op_input_index != -1);
+ assert(op_output_index != -1);
+ const auto input = main_runtime_graph->getCircleTensorByIndex(op_input_index);
+ const auto output = main_runtime_graph->getCircleTensorByIndex(op_output_index);
+
+ if (main_runtime_graph->getDataByTensor(input))
+ {
+ main_runtime_graph->makeInplaceOperation(input, output);
+ }
+ else
+ {
+ main_runtime_graph->setDataToTensor(output, operation_inputs_data[i]);
+ }
+ }
}
-
- copy(cond_inputs, getOutputTensors());
}
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/While.h b/onert-micro/luci-interpreter/src/kernels/While.h
deleted file mode 100644
index 56f98badb..000000000
--- a/onert-micro/luci-interpreter/src/kernels/While.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_WHILE_H
-#define LUCI_INTERPRETER_KERNELS_WHILE_H
-
-#include "core/Kernel.h"
-#include "core/RuntimeGraph.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class While : public Kernel
-{
-public:
- While(std::vector<const Tensor *> inputs, std::vector<Tensor *> outputs, RuntimeGraph *cond_graph,
- RuntimeGraph *body_graph);
-
- const Tensor *input(int index) const { return _inputs[index]; }
- Tensor *output(int index) const { return _outputs[index]; }
-
- void configure() override;
- void execute() const override;
-
-private:
- RuntimeGraph *const _cond_graph = nullptr;
- RuntimeGraph *const _body_graph = nullptr;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_WHILE_H
diff --git a/onert-micro/luci-interpreter/src/kernels/While.test.cpp b/onert-micro/luci-interpreter/src/kernels/While.test.cpp
index cb8f89130..4873b9c04 100644
--- a/onert-micro/luci-interpreter/src/kernels/While.test.cpp
+++ b/onert-micro/luci-interpreter/src/kernels/While.test.cpp
@@ -15,87 +15,73 @@
* limitations under the License.
*/
-#include "core/RuntimeModule.h"
-#include "kernels/Add.h"
-#include "kernels/Less.h"
-#include "kernels/While.h"
#include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/while/WhileKernel.h"
+#include "luci_interpreter/test_models/while/NegWhileKernel.h"
+
+#include "loader/ModuleLoader.h"
namespace luci_interpreter
{
-namespace kernels
-{
namespace
{
using namespace testing;
-RuntimeGraph *buildCondSubgraph(RuntimeModule *module, DataType dtype, Tensor *input_cond,
- IMemoryManager *memory_manager)
+class WhileTest : public ::testing::Test
{
- RuntimeGraph *graph = module->addGraph(memory_manager);
- Tensor *input =
- graph->addTensor(std::make_unique<Tensor>(dtype, Shape{}, AffineQuantization{}, ""));
- Tensor *output =
- graph->addTensor(std::make_unique<Tensor>(DataType::BOOL, Shape{}, AffineQuantization{}, ""));
-
- memory_manager->allocate_memory(*input);
- memory_manager->allocate_memory(*output);
+ // Do nothing
+};
- graph->setInputTensors({input});
- graph->setOutputTensors({output});
-
- graph->addKernel(std::make_unique<Less>(input, input_cond, output));
+template <typename T> std::vector<T> checkWhileKernel(test_kernel::TestDataBase<T> *test_data_base)
+{
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
- return graph;
-}
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_base->get_model_ptr());
+ ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input);
-RuntimeGraph *buildBodySubgraph(RuntimeModule *module, DataType dtype, Tensor *input_add,
- IMemoryManager *memory_manager)
-{
- RuntimeGraph *graph = module->addGraph(memory_manager);
- Tensor *input =
- graph->addTensor(std::make_unique<Tensor>(dtype, Shape{}, AffineQuantization{}, ""));
- Tensor *output =
- graph->addTensor(std::make_unique<Tensor>(dtype, Shape{}, AffineQuantization{}, ""));
+ auto *main_runtime_graph = runtime_module.getMainGraph();
+ assert(main_runtime_graph->getNumOfInputTensors() == 1);
- memory_manager->allocate_memory(*input);
- memory_manager->allocate_memory(*output);
+ // Set input data
+ {
+ auto *input_tensor_data = reinterpret_cast<T *>(main_runtime_graph->configureGraphInput(0));
+ std::copy(test_data_base->get_input_data_by_index(0).begin(),
+ test_data_base->get_input_data_by_index(0).end(), input_tensor_data);
+ }
- graph->setInputTensors({input});
- graph->setOutputTensors({output});
+ runtime_module.execute();
- AddParams params{};
- params.activation = Activation::NONE;
- graph->addKernel(std::make_unique<Add>(input, input_add, output, params));
+ assert(main_runtime_graph->getNumOfOutputTensors() == 1);
- return graph;
+ T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+ const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+ std::vector<T> output_data_vector(output_data, output_data + num_elements);
+ return output_data_vector;
}
-TEST(WhileTest, FloatLoop10)
+TEST_F(WhileTest, MainTest_P)
{
- std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
- Tensor input = makeInputTensor<DataType::FLOAT32>({1}, {1}, memory_manager.get());
- Tensor output = makeOutputTensor(DataType::FLOAT32);
-
- Tensor input_cond = makeInputTensor<DataType::FLOAT32>({1}, {10}, memory_manager.get());
- Tensor input_add = makeInputTensor<DataType::FLOAT32>({1}, {1}, memory_manager.get());
-
- RuntimeModule module(nullptr);
- RuntimeGraph *cond_graph =
- buildCondSubgraph(&module, DataType::FLOAT32, &input_cond, memory_manager.get());
- RuntimeGraph *body_graph =
- buildBodySubgraph(&module, DataType::FLOAT32, &input_add, memory_manager.get());
-
- While kernel({&input}, {&output}, cond_graph, body_graph);
- kernel.configure();
- memory_manager->allocate_memory(output);
- kernel.execute();
+ test_kernel::TestDataWhileKernel<int32_t> test_data_kernel;
+ std::vector<int32_t> output_data_vector = checkWhileKernel(&test_data_kernel);
+ EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
- EXPECT_THAT(extractTensorData<float>(output), FloatArrayNear({10}));
+TEST_F(WhileTest, MainTest_NEG)
+{
+ test_kernel::NegTestDataWhileKernel test_data_kernel;
+
+ MemoryManager memory_manager{};
+ RuntimeModule runtime_module{};
+ bool dealloc_input = true;
+ // Load model with single op
+ auto *model_data_raw = reinterpret_cast<const char *>(test_data_kernel.get_model_ptr());
+ EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input),
+ "");
}
} // namespace
-} // namespace kernels
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/GraphLoader.cpp b/onert-micro/luci-interpreter/src/loader/GraphLoader.cpp
index cb9dd7fea..26e207ac0 100644
--- a/onert-micro/luci-interpreter/src/loader/GraphLoader.cpp
+++ b/onert-micro/luci-interpreter/src/loader/GraphLoader.cpp
@@ -21,38 +21,62 @@ namespace luci_interpreter
namespace
{
-// TODO: add more operations
-bool isCouldBeEmplaceOperation(circle::BuiltinOperator op)
+bool isInplaceOperation(const circle::BuiltinOperator &op)
{
switch (op)
{
+ case circle::BuiltinOperator_ABS:
case circle::BuiltinOperator_LOGISTIC:
case circle::BuiltinOperator_RESHAPE:
+ case circle::BuiltinOperator_ELU:
case circle::BuiltinOperator_EXPAND_DIMS:
+ case circle::BuiltinOperator_EXP:
+ case circle::BuiltinOperator_TANH:
+ case circle::BuiltinOperator_LEAKY_RELU:
+ case circle::BuiltinOperator_RELU:
+ case circle::BuiltinOperator_RELU6:
+ case circle::BuiltinOperator_ADD:
+ case circle::BuiltinOperator_MUL:
+ case circle::BuiltinOperator_SUB:
+ case circle::BuiltinOperator_WHILE:
return true;
default:
return false;
}
}
-bool isCouldBeEmplaceTensor(CircleReader *reader, const int32_t tensor_index)
+bool isSingleUsageOfTensor(CircleReader *reader, const int32_t tensor_index)
{
uint32_t usage_count = 0;
- for (uint32_t i = 0; i < reader->operators().size(); ++i)
+
+ const auto operators = reader->operators();
+ for (uint32_t i = 0; i < operators.size(); ++i)
{
- const auto op = reader->operators().at(i);
+ const auto *op = operators.at(i);
assert(op != nullptr);
- for (int32_t j = 0; j < op->inputs()->size(); ++j)
+ const auto *op_inputs = op->inputs();
+ for (int32_t j = 0; j < op_inputs->size(); ++j)
{
- const auto input_index = op->inputs()->operator[](j);
+ const auto input_index = op_inputs->operator[](j);
if (input_index == tensor_index)
- usage_count++;
-
- if (usage_count > 1)
- return false;
+ {
+ if (++usage_count > 1)
+ return false;
+ }
}
}
+
+ // Let's check that it is not graph output
+ if (usage_count == 1)
+ {
+ const auto &outputs_indexes = reader->outputs();
+ bool is_graph_output = (std::find(outputs_indexes.begin(), outputs_indexes.end(),
+ tensor_index) != outputs_indexes.end());
+ if (is_graph_output)
+ return false;
+ }
+
return true;
}
@@ -60,29 +84,83 @@ bool isCouldBeEmplaceTensor(CircleReader *reader, const int32_t tensor_index)
void GraphLoader::checkInplaceOps(CircleReader *reader, RuntimeGraph *runtime_graph)
{
- for (uint32_t i = 0; i < reader->operators().size(); ++i)
+ const auto operators = reader->operators();
+ const auto graph_outputs = reader->outputs();
+ for (uint32_t i = 0; i < operators.size(); ++i)
{
- const auto *op = reader->operators().at(i);
+ const auto *op = operators.at(i);
assert(op != nullptr);
- bool is_graph_input = false;
- for (int32_t j = 0; j < op->inputs()->size(); ++j)
+ // Check inplace optimization for operation with single input and single output
+ if (isInplaceOperation(reader->builtin_code(op)))
{
- const auto input_index = op->inputs()->operator[](j);
- if (input_index == -1)
- continue;
+ const auto *op_inputs = op->inputs();
+ const auto *op_outputs = op->outputs();
- const auto &inputs_indexes = reader->inputs();
+ bool is_inplace = true;
+ auto non_const_input_it = op_inputs->begin();
+ while (true)
+ {
+ non_const_input_it =
+ std::find_if(non_const_input_it, op_inputs->end(), [&reader](const auto input_idx) {
+ if (input_idx == -1)
+ return false;
- is_graph_input = (std::find(inputs_indexes.begin(), inputs_indexes.end(), input_index) !=
- inputs_indexes.end()) or
- is_graph_input;
+ return not Tensor::is_constant_tensor(reader, reader->tensors()[input_idx]);
+ });
- if (not is_graph_input and isCouldBeEmplaceOperation(reader->builtin_code(op)) and
- op->outputs()->size() == 1 and isCouldBeEmplaceTensor(reader, input_index))
- {
- runtime_graph->addInplaceOpIndex(i);
+ if (non_const_input_it == op_inputs->end())
+ break;
+
+ auto dist = std::distance(op_inputs->begin(), non_const_input_it);
+
+ const auto non_const_input_idx = *non_const_input_it;
+
+ // Check single usage of input tensor
+ if (not isSingleUsageOfTensor(reader, non_const_input_idx))
+ {
+ is_inplace = false;
+ break;
+ }
+
+ // Let's check single usage of output tensor
+ if (dist >= op_outputs->size() and op_outputs->size() == 1)
+ dist = 0;
+ assert(dist < op_outputs->size());
+ const auto output_index = op_outputs->operator[](dist);
+ if (not isSingleUsageOfTensor(reader, output_index))
+ {
+ is_inplace = false;
+ break;
+ }
+
+ // Check that num elements are equal
+ {
+ const auto *input_non_const_tensor = reader->tensors().at(non_const_input_idx);
+ const auto *output_tensor = reader->tensors().at(output_index);
+ if (Tensor::num_elements(input_non_const_tensor) != Tensor::num_elements(output_tensor))
+ {
+ is_inplace = false;
+ break;
+ }
+ }
+
+ // Let's check that output is not a graph output tensor
+ // TODO: check this statement
+ {
+ if (std::find(graph_outputs.begin(), graph_outputs.end(), output_index) !=
+ graph_outputs.end())
+ {
+ is_inplace = false;
+ break;
+ }
+ }
+
+ non_const_input_it++;
}
+
+ if (is_inplace)
+ runtime_graph->addInplaceOpIndex(op);
}
}
}
diff --git a/onert-micro/luci-interpreter/src/loader/ModuleLoader.cpp b/onert-micro/luci-interpreter/src/loader/ModuleLoader.cpp
index 0bb38c604..dcfa32983 100644
--- a/onert-micro/luci-interpreter/src/loader/ModuleLoader.cpp
+++ b/onert-micro/luci-interpreter/src/loader/ModuleLoader.cpp
@@ -22,7 +22,7 @@ namespace luci_interpreter
{
void ModuleLoader::load(RuntimeModule *runtime_module, SimpleMemoryManager *memory_manager,
- const char *model_data_raw)
+ const char *model_data_raw, bool dealloc_input)
{
const circle::Model *model = circle::GetModel(model_data_raw);
@@ -32,19 +32,16 @@ void ModuleLoader::load(RuntimeModule *runtime_module, SimpleMemoryManager *memo
for (size_t i = 0; i < reader.num_subgraph(); ++i)
{
+ if (!reader.select_subgraph(i))
+ assert(false && "Error during select subgraph");
runtime_module->addGraph(memory_manager);
- }
#ifndef USE_STATIC_ALLOC
- for (size_t i = 0; i < reader.num_subgraph(); ++i)
- {
- if (!reader.select_subgraph(i))
- assert(false && "Error during select subgraph");
auto *runtime_graph = runtime_module->getRuntimeGraphAt(i);
// For Dynamic memory manager we can use inplace optimization
GraphLoader::checkInplaceOps(&reader, runtime_graph);
- }
#endif // USE_STATIC_ALLOC
+ }
// For Dynamic Memory manager we build memory allocate/deallocate plan and then configure kernels.
// For Static Memory manager we only configure kernels.
@@ -54,9 +51,12 @@ void ModuleLoader::load(RuntimeModule *runtime_module, SimpleMemoryManager *memo
#ifdef USE_STATIC_ALLOC
runtime_graph->configure_kernels();
#else
- runtime_graph->configure();
+ runtime_graph->configure(dealloc_input);
#endif // USE_STATIC_ALLOC
}
+
+ // Select main subgraph
+ reader.select_subgraph(0);
}
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/ModuleLoader.h b/onert-micro/luci-interpreter/src/loader/ModuleLoader.h
index c35c72da9..bfe3e7076 100644
--- a/onert-micro/luci-interpreter/src/loader/ModuleLoader.h
+++ b/onert-micro/luci-interpreter/src/loader/ModuleLoader.h
@@ -29,7 +29,7 @@ class ModuleLoader
{
public:
static void load(RuntimeModule *runtime_module, MemoryManager *memory_manager,
- const char *model_data_raw);
+ const char *model_data_raw, bool dealloc_input);
};
} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Add.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Add.cpp
deleted file mode 100644
index 2a2140b0f..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Add.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Add.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleAdd(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
-
- const Tensor *input1 = inputs.at(0);
- const Tensor *input2 = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsAddOptions();
-
- AddParams params{};
- params.activation = luci_actfunc(options->fused_activation_function);
-
- return std::make_unique<kernels::Add>(input1, input2, output, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/ArgMax.cpp b/onert-micro/luci-interpreter/src/loader/nodes/ArgMax.cpp
deleted file mode 100644
index 0da72daab..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/ArgMax.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/ArgMax.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleArgMax(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
-
- const Tensor *input = inputs.at(0);
- const Tensor *axis = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsArgMaxOptions();
-
- ArgMaxParams params{};
- params.output_type = static_cast<DataType>(options->output_type);
-
- return std::make_unique<kernels::ArgMax>(input, axis, output, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/AveragePool2D.cpp b/onert-micro/luci-interpreter/src/loader/nodes/AveragePool2D.cpp
deleted file mode 100644
index 9a5af1c37..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/AveragePool2D.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/AveragePool2D.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleAveragePool2D(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 1);
-
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsPool2DOptions();
-
- Pool2DParams params{};
- params.padding = luci_padding(options->padding);
- params.filter_height = options->filter_height;
- params.filter_width = options->filter_width;
- params.stride_height = options->stride_h;
- params.stride_width = options->stride_w;
- params.activation = luci_actfunc(options->fused_activation_function);
-
- // It is unknown what data will be stored in scratchpad tensor,
- // using UINT8 as a most general option
- auto scratchpad = std::make_unique<Tensor>(DataType::U8, Shape({}), nullptr);
- scratchpad->set_data_buffer(nullptr);
- // TODO move tensors offset initialization to one place
- // TODO handle with static manager
- Tensor *tmp = builder.get_runtime_graph()->addTensor(std::move(scratchpad));
-
- return std::make_unique<kernels::AveragePool2D>(input, output, tmp, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/BatchMatMul.cpp b/onert-micro/luci-interpreter/src/loader/nodes/BatchMatMul.cpp
deleted file mode 100644
index 7799331d6..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/BatchMatMul.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/BatchMatMul.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleBatchMatMul(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
-
- const Tensor *lhs = inputs.at(0);
- const Tensor *rhs = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- auto lhs_scratchpad = std::make_unique<Tensor>(lhs->element_type(), Shape({}), nullptr);
- lhs_scratchpad->set_data_buffer(nullptr);
- auto rhs_scratchpad = std::make_unique<Tensor>(rhs->element_type(), Shape({}), nullptr);
- rhs_scratchpad->set_data_buffer(nullptr);
- // TODO move tensors offset initialization to one place
- // TODO handle with StaticManager
- Tensor *lhs_tmp = builder.get_runtime_graph()->addTensor(std::move(lhs_scratchpad));
- Tensor *rhs_tmp = builder.get_runtime_graph()->addTensor(std::move(rhs_scratchpad));
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsBatchMatMulOptions();
-
- BatchMatMulParams params;
- params.adj_x = options->adjoint_lhs;
- params.adj_y = options->adjoint_rhs;
-
- return std::make_unique<kernels::BatchMatMul>(lhs, rhs, output, lhs_tmp, rhs_tmp, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/BatchToSpaceND.cpp b/onert-micro/luci-interpreter/src/loader/nodes/BatchToSpaceND.cpp
deleted file mode 100644
index 424844a3c..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/BatchToSpaceND.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/BatchToSpaceND.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleBatchToSpaceND(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 3);
-
- const Tensor *input = inputs.at(0);
- const Tensor *block_shape = inputs.at(1);
- const Tensor *crops = inputs.at(2);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::BatchToSpaceND>(input, block_shape, crops, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Concatenation.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Concatenation.cpp
deleted file mode 100644
index e2b847a3a..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Concatenation.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Concatenation.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleConcatenation(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- std::vector<const Tensor *> input_tensors(inputs.size());
- for (uint32_t i = 0; i < inputs.size(); ++i)
- {
- input_tensors[i] = inputs.at(i);
- }
- Tensor *output = outputs.at(0);
- ;
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsConcatenationOptions();
-
- ConcatenationParams params{};
- params.axis = options->axis;
- params.activation = luci_actfunc(options->fused_activation_function);
-
- return std::make_unique<kernels::Concatenation>(std::move(input_tensors), output, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Conv2D.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Conv2D.cpp
deleted file mode 100644
index 1750e8afc..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Conv2D.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Conv2D.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleConv2D(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 3);
-
- const Tensor *input = inputs.at(0);
- const Tensor *filter = inputs.at(1);
- const Tensor *bias = inputs.at(2);
- Tensor *output = outputs.at(0);
-
- // It is unknown what data will be stored in scratchpad tensor,
- // using UINT8 as a most general option
- auto scratchpad = std::make_unique<Tensor>(DataType::U8, Shape({}), nullptr);
- scratchpad->set_data_buffer(nullptr);
- // TODO move tensors offset initialization to one place
- // TODO handle with StaticManager
- Tensor *tmp = builder.get_runtime_graph()->addTensor(std::move(scratchpad));
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsConv2DOptions();
-
- Conv2DParams params{};
- params.padding = luci_padding(options->padding);
- params.stride_height = options->stride_h;
- params.stride_width = options->stride_w;
- params.dilation_height_factor = options->dilation_h_factor;
- params.dilation_width_factor = options->dilation_w_factor;
- params.activation = luci_actfunc(options->fused_activation_function);
-
- return std::make_unique<kernels::Conv2D>(input, filter, bias, output, tmp, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/DepthToSpace.cpp b/onert-micro/luci-interpreter/src/loader/nodes/DepthToSpace.cpp
deleted file mode 100644
index ebab0ccec..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/DepthToSpace.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/DepthToSpace.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleDepthToSpace(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 1);
-
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsDepthToSpaceOptions();
-
- DepthToSpaceParams params{};
- params.block_size = options->block_size;
-
- return std::make_unique<kernels::DepthToSpace>(input, output, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/DepthwiseConv2D.cpp b/onert-micro/luci-interpreter/src/loader/nodes/DepthwiseConv2D.cpp
deleted file mode 100644
index cebad555a..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/DepthwiseConv2D.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/DepthwiseConv2D.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleDepthwiseConv2D(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 3);
-
- const Tensor *input = inputs.at(0);
- const Tensor *filter = inputs.at(1);
- const Tensor *bias = inputs.at(2);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsDepthwiseConv2DOptions();
-
- DepthwiseConv2DParams params{};
- params.padding = luci_padding(options->padding);
- params.depth_multiplier = options->depth_multiplier;
- params.stride_height = options->stride_h;
- params.stride_width = options->stride_w;
- params.dilation_height_factor = options->dilation_h_factor;
- params.dilation_width_factor = options->dilation_w_factor;
- params.activation = luci_actfunc(options->fused_activation_function);
-
- // It is unknown what data will be stored in scratchpad tensor,
- // using UINT8 as a most general option
- auto scratchpad = std::make_unique<Tensor>(DataType::U8, Shape({}), nullptr);
- scratchpad->set_data_buffer(nullptr);
- // TODO move tensors offset initialization to one place
- // TODO handle with StaticManager
- Tensor *tmp = builder.get_runtime_graph()->addTensor(std::move(scratchpad));
-
- return std::make_unique<kernels::DepthwiseConv2D>(input, filter, bias, output, tmp, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Dequantize.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Dequantize.cpp
deleted file mode 100644
index 06b75187b..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Dequantize.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Dequantize.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleDequantize(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::Dequantize>(input, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Div.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Div.cpp
deleted file mode 100644
index 3331df91f..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Div.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Div.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleDiv(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
- const Tensor *input1 = inputs.at(0);
- const Tensor *input2 = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsDivOptions();
-
- DivParams params{};
- params.activation = luci_actfunc(options->fused_activation_function);
-
- return std::make_unique<kernels::Div>(input1, input2, output, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Elu.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Elu.cpp
deleted file mode 100644
index 2d8932803..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Elu.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Elu.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleElu(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 1);
-
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::Elu>(input, output);
-}
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Equal.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Equal.cpp
deleted file mode 100644
index eee500945..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Equal.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Equal.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleEqual(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-
-{
- assert(inputs.size() == 2);
-
- const Tensor *x = inputs.at(0);
- const Tensor *y = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::Equal>(x, y, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/ExpandDims.cpp b/onert-micro/luci-interpreter/src/loader/nodes/ExpandDims.cpp
deleted file mode 100644
index f4745b3f6..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/ExpandDims.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/ExpandDims.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleExpandDims(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
- const Tensor *input = inputs.at(0);
- const Tensor *axis = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::ExpandDims>(input, axis, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Fill.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Fill.cpp
deleted file mode 100644
index cd5a3368c..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Fill.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Fill.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleFill(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
- const Tensor *dims = inputs.at(0);
- const Tensor *value = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::Fill>(dims, value, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/FloorDiv.cpp b/onert-micro/luci-interpreter/src/loader/nodes/FloorDiv.cpp
deleted file mode 100644
index 7caf12371..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/FloorDiv.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/FloorDiv.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleFloorDiv(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
- const Tensor *x = inputs.at(0);
- const Tensor *y = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::FloorDiv>(x, y, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/FullyConnected.cpp b/onert-micro/luci-interpreter/src/loader/nodes/FullyConnected.cpp
deleted file mode 100644
index cb35c0f68..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/FullyConnected.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/FullyConnected.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleFullyConnected(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 3);
-
- const Tensor *input = inputs.at(0);
- const Tensor *weights = inputs.at(1);
- const Tensor *bias = inputs.at(2);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsFullyConnectedOptions();
-
- FullyConnectedParams params{};
- params.activation = luci_actfunc(options->fused_activation_function);
- params.keep_num_dims = options->keep_num_dims;
-
- return std::make_unique<kernels::FullyConnected>(input, weights, bias, output, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Gather.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Gather.cpp
deleted file mode 100644
index 02cb7e652..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Gather.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Gather.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleGather(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
- const Tensor *params = inputs.at(0);
- const Tensor *indices = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsGatherOptions();
-
- GatherParams gparams{};
- gparams.axis = options->axis;
- // TODO support batch_dims
- gparams.batch_dims = 0;
-
- return std::make_unique<kernels::Gather>(params, indices, output, gparams);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Greater.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Greater.cpp
deleted file mode 100644
index 160911eb8..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Greater.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Greater.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleGreater(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
- const Tensor *x = inputs.at(0);
- const Tensor *y = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::Greater>(x, y, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/GreaterEqual.cpp b/onert-micro/luci-interpreter/src/loader/nodes/GreaterEqual.cpp
deleted file mode 100644
index 4c196823c..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/GreaterEqual.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/GreaterEqual.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleGreaterEqual(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
- const Tensor *x = inputs.at(0);
- const Tensor *y = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::GreaterEqual>(x, y, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/InstanceNorm.cpp b/onert-micro/luci-interpreter/src/loader/nodes/InstanceNorm.cpp
deleted file mode 100644
index 1d7f63900..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/InstanceNorm.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/InstanceNorm.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleInstanceNorm(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 3);
-
- const Tensor *input = inputs.at(0);
- const Tensor *gamma = inputs.at(1);
- const Tensor *beta = inputs.at(2);
-
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsInstanceNormOptions();
-
- InstanceNormParams params{};
- params.epsilon = options->epsilon;
- params.activation = luci_actfunc(options->fused_activation_function);
-
- return std::make_unique<kernels::InstanceNorm>(input, gamma, beta, output, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/L2Normalize.cpp b/onert-micro/luci-interpreter/src/loader/nodes/L2Normalize.cpp
deleted file mode 100644
index 6435f0909..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/L2Normalize.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/L2Normalize.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleL2Normalize(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 1);
-
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsL2NormOptions();
-
- L2NormParams params{};
- params.activation = luci_actfunc(options->fused_activation_function);
-
- return std::make_unique<kernels::L2Normalize>(input, output, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/L2Pool2D.cpp b/onert-micro/luci-interpreter/src/loader/nodes/L2Pool2D.cpp
deleted file mode 100644
index d297525bf..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/L2Pool2D.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/L2Pool2D.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleL2Pool2D(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 1);
-
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsPool2DOptions();
-
- Pool2DParams params{};
- params.padding = luci_padding(options->padding);
- params.filter_height = options->filter_height;
- params.filter_width = options->filter_width;
- params.stride_height = options->stride_h;
- params.stride_width = options->stride_w;
- params.activation = luci_actfunc(options->fused_activation_function);
-
- return std::make_unique<kernels::L2Pool2D>(input, output, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/LeakyRelu.cpp b/onert-micro/luci-interpreter/src/loader/nodes/LeakyRelu.cpp
deleted file mode 100644
index 2cb27e2a4..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/LeakyRelu.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/LeakyRelu.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleLeakyRelu(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 1);
-
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsLeakyReluOptions();
-
- LeakyReluParams params{};
- params.alpha = options->alpha;
-
- return std::make_unique<kernels::LeakyRelu>(input, output, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Less.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Less.cpp
deleted file mode 100644
index 9de9dbe94..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Less.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Less.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleLess(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
-
- const Tensor *x = inputs.at(0);
- const Tensor *y = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::Less>(x, y, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/LocalResponseNormalization.cpp b/onert-micro/luci-interpreter/src/loader/nodes/LocalResponseNormalization.cpp
deleted file mode 100644
index 71ed6348d..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/LocalResponseNormalization.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/LocalResponseNormalization.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel>
-build_kernel_CircleLocalResponseNormalization(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 1);
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsLocalResponseNormalizationOptions();
-
- LocalResponseNormalizationParams params{};
- params.radius = options->radius;
- params.bias = options->bias;
- params.alpha = options->alpha;
- params.beta = options->beta;
-
- return std::make_unique<kernels::LocalResponseNormalization>(input, output, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/LogSoftmax.cpp b/onert-micro/luci-interpreter/src/loader/nodes/LogSoftmax.cpp
deleted file mode 100644
index 03e40e98b..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/LogSoftmax.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/LogSoftmax.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleLogSoftmax(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 1);
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::LogSoftmax>(input, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/LogicalAnd.cpp b/onert-micro/luci-interpreter/src/loader/nodes/LogicalAnd.cpp
deleted file mode 100644
index 32677a7b4..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/LogicalAnd.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/LogicalAnd.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleLogicalAnd(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
-
- const Tensor *input1 = inputs.at(0);
- const Tensor *input2 = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::LogicalAnd>(input1, input2, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/LogicalNot.cpp b/onert-micro/luci-interpreter/src/loader/nodes/LogicalNot.cpp
deleted file mode 100644
index 43ec1e491..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/LogicalNot.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/LogicalNot.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleLogicalNot(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 1);
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::LogicalNot>(input, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/LogicalOr.cpp b/onert-micro/luci-interpreter/src/loader/nodes/LogicalOr.cpp
deleted file mode 100644
index 7ce29a883..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/LogicalOr.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/LogicalOr.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleLogicalOr(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
-
- const Tensor *input1 = inputs.at(0);
- const Tensor *input2 = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::LogicalOr>(input1, input2, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Logistic.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Logistic.cpp
deleted file mode 100644
index 113b5eab4..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Logistic.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Logistic.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleLogistic(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 1);
-
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::Logistic>(input, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/MaxPool2D.cpp b/onert-micro/luci-interpreter/src/loader/nodes/MaxPool2D.cpp
deleted file mode 100644
index 40fff4df5..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/MaxPool2D.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/MaxPool2D.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleMaxPool2D(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 1);
-
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsPool2DOptions();
-
- Pool2DParams params{};
- params.padding = luci_padding(options->padding);
- params.filter_height = options->filter_height;
- params.filter_width = options->filter_width;
- params.stride_height = options->stride_h;
- params.stride_width = options->stride_w;
- params.activation = luci_actfunc(options->fused_activation_function);
-
- return std::make_unique<kernels::MaxPool2D>(input, output, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Maximum.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Maximum.cpp
deleted file mode 100644
index 1a7930a1a..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Maximum.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Maximum.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleMaximum(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
-
- const Tensor *input1 = inputs.at(0);
- const Tensor *input2 = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::Maximum>(input1, input2, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Mean.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Mean.cpp
deleted file mode 100644
index 6ef48bc95..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Mean.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Mean.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleMean(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
-
- const Tensor *input = inputs.at(0);
- const Tensor *axis = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- auto temp_index_unique = std::make_unique<Tensor>(DataType::S32, Shape({}), nullptr);
- temp_index_unique->set_data_buffer(nullptr);
- Tensor *temp_index = builder.get_runtime_graph()->addTensor(std::move(temp_index_unique));
-
- auto resolved_axes_unique = std::make_unique<Tensor>(DataType::S32, Shape({}), nullptr);
- resolved_axes_unique->set_data_buffer(nullptr);
- Tensor *resolved_axes = builder.get_runtime_graph()->addTensor(std::move(resolved_axes_unique));
-
- auto temp_sum_unique = std::make_unique<Tensor>(input->element_type(), Shape({}), nullptr);
- temp_sum_unique->set_data_buffer(nullptr);
- Tensor *temp_sum = builder.get_runtime_graph()->addTensor(std::move(temp_sum_unique));
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsReducerOptions();
-
- ReducerParams params{};
- params.keep_dims = options->keep_dims;
-
- return std::make_unique<kernels::Mean>(input, axis, output, temp_index, resolved_axes, temp_sum,
- params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Minimum.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Minimum.cpp
deleted file mode 100644
index 232ebf020..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Minimum.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Minimum.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleMinimum(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
-
- const Tensor *input1 = inputs.at(0);
- const Tensor *input2 = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::Minimum>(input1, input2, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/MirrorPad.cpp b/onert-micro/luci-interpreter/src/loader/nodes/MirrorPad.cpp
deleted file mode 100644
index d96ad2500..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/MirrorPad.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/MirrorPad.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleMirrorPad(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
-
- const Tensor *input = inputs.at(0);
- const Tensor *paddings = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsMirrorPadOptions();
-
- MirrorPadParams params{};
- params.mode = luci_mirrorpad_mode(options->mode);
-
- return std::make_unique<kernels::MirrorPad>(input, paddings, output, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Mul.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Mul.cpp
deleted file mode 100644
index 283f0427a..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Mul.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Mul.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleMul(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
-
- const Tensor *input1 = inputs.at(0);
- const Tensor *input2 = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsMulOptions();
-
- MulParams params{};
- params.activation = luci_actfunc(options->fused_activation_function);
-
- return std::make_unique<kernels::Mul>(input1, input2, output, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/NotEqual.cpp b/onert-micro/luci-interpreter/src/loader/nodes/NotEqual.cpp
deleted file mode 100644
index 1c8493146..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/NotEqual.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/NotEqual.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleNotEqual(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
-
- const Tensor *x = inputs.at(0);
- const Tensor *y = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::NotEqual>(x, y, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/OneHot.cpp b/onert-micro/luci-interpreter/src/loader/nodes/OneHot.cpp
deleted file mode 100644
index a1c8a5bf5..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/OneHot.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/OneHot.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleOneHot(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 4);
-
- const Tensor *indices = inputs.at(0);
- const Tensor *depth = inputs.at(1);
- const Tensor *on_value = inputs.at(2);
- const Tensor *off_value = inputs.at(3);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsOneHotOptions();
-
- OneHotParams params{};
- params.axis = options->axis;
-
- return std::make_unique<kernels::OneHot>(indices, depth, on_value, off_value, output, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Pack.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Pack.cpp
deleted file mode 100644
index a92196b4e..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Pack.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Pack.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CirclePack(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- std::vector<const Tensor *> input_tensors(inputs.size());
- for (uint32_t i = 0; i < inputs.size(); ++i)
- {
- input_tensors[i] = inputs.at(i);
- }
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsPackOptions();
-
- PackParams params{};
- params.axis = options->axis;
- params.values_count = options->values_count;
-
- return std::make_unique<kernels::Pack>(std::move(input_tensors), output, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Pad.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Pad.cpp
deleted file mode 100644
index 26aa7e761..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Pad.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Pad.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CirclePad(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
-
- const Tensor *input = inputs.at(0);
- const Tensor *paddings = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::Pad>(input, paddings, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/PadV2.cpp b/onert-micro/luci-interpreter/src/loader/nodes/PadV2.cpp
deleted file mode 100644
index 829c47f3e..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/PadV2.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/PadV2.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CirclePadV2(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 3);
-
- const Tensor *input = inputs.at(0);
- const Tensor *paddings = inputs.at(1);
- const Tensor *constant_values = inputs.at(2);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::PadV2>(input, paddings, constant_values, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Pow.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Pow.cpp
deleted file mode 100644
index 005c28132..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Pow.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Pow.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CirclePow(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
-
- const Tensor *input1 = inputs.at(0);
- const Tensor *input2 = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::Pow>(input1, input2, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Quantize.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Quantize.cpp
deleted file mode 100644
index 4fa7e66ab..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Quantize.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Quantize.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleQuantize(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 1);
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::Quantize>(input, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Relu.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Relu.cpp
deleted file mode 100644
index 27fcb6b40..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Relu.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Relu.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleRelu(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 1);
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::Relu>(input, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Relu6.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Relu6.cpp
deleted file mode 100644
index 68dba2c44..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Relu6.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Relu6.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleRelu6(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 1);
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::Relu6>(input, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Reshape.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Reshape.cpp
deleted file mode 100644
index 45ebf0a50..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Reshape.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Reshape.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleReshape(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
-
- const Tensor *input = inputs.at(0);
- const Tensor *shape = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- // NOTE 'newShape' attribute is ignored.
- return std::make_unique<kernels::Reshape>(input, shape, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/ResizeBilinear.cpp b/onert-micro/luci-interpreter/src/loader/nodes/ResizeBilinear.cpp
deleted file mode 100644
index bd82048a5..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/ResizeBilinear.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/ResizeBilinear.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleResizeBilinear(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
-
- const Tensor *input = inputs.at(0);
- const Tensor *size = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsResizeBilinearOptions();
-
- ResizeBilinearParams params{};
- params.align_corners = options->align_corners;
- params.half_pixel_centers = options->half_pixel_centers;
-
- return std::make_unique<kernels::ResizeBilinear>(input, size, output, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/ResizeNearestNeighbor.cpp b/onert-micro/luci-interpreter/src/loader/nodes/ResizeNearestNeighbor.cpp
deleted file mode 100644
index bc59e87bb..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/ResizeNearestNeighbor.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/ResizeNearestNeighbor.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel>
-build_kernel_CircleResizeNearestNeighbor(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs, const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
-
- const Tensor *input = inputs.at(0);
- const Tensor *size = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsResizeNearestNeighborOptions();
-
- ResizeNearestNeighborParams params{};
- params.align_corners = options->align_corners;
- // TODO update half_pixel_centers after CircleResizeNearestNeighbor updated
- // Current CircleResizeNearestNeighbor don't have half_pixel_centers.
- // default value on current is false.
- // it need to be updated when CircleResizeNearestNeighbor updated.
- params.half_pixel_centers = false;
-
- return std::make_unique<kernels::ResizeNearestNeighbor>(input, size, output, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/ReverseV2.cpp b/onert-micro/luci-interpreter/src/loader/nodes/ReverseV2.cpp
deleted file mode 100644
index 0b23ee0ce..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/ReverseV2.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/ReverseV2.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleReverseV2(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
-
- const Tensor *input = inputs.at(0);
- const Tensor *axis = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::ReverseV2>(input, axis, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Rsqrt.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Rsqrt.cpp
deleted file mode 100644
index 87ca438a7..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Rsqrt.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Rsqrt.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleRsqrt(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 1);
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::Rsqrt>(input, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/SVDF.cpp b/onert-micro/luci-interpreter/src/loader/nodes/SVDF.cpp
deleted file mode 100644
index 8a77459ea..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/SVDF.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/SVDF.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleSVDF(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 5);
-
- const Tensor *input = inputs.at(0);
- const Tensor *feature = inputs.at(1);
- const Tensor *time = inputs.at(2);
- const Tensor *bias = inputs.at(3);
- const Tensor *input_activation_state = inputs.at(4);
- Tensor *output = outputs.at(0);
-
- auto scratchpad_tensor =
- std::make_unique<Tensor>(input_activation_state->element_type(), Shape({}), nullptr);
- scratchpad_tensor->set_data_buffer(nullptr);
- Tensor *tmp = builder.get_runtime_graph()->addTensor(std::move(scratchpad_tensor));
-
- DataType data_type = input->element_type() == DataType::S8 ? DataType::S32 : DataType::FLOAT32;
-
- scratchpad_tensor = std::make_unique<Tensor>(data_type, Shape({}), nullptr);
- scratchpad_tensor->set_data_buffer(nullptr);
- Tensor *tmp_1 = builder.get_runtime_graph()->addTensor(std::move(scratchpad_tensor));
-
- if (data_type == DataType::FLOAT32 &&
- (feature->element_type() == DataType::S8 || feature->element_type() == DataType::U8))
- {
- data_type = feature->element_type();
- }
-
- scratchpad_tensor = std::make_unique<Tensor>(data_type, Shape({}), nullptr);
- scratchpad_tensor->set_data_buffer(nullptr);
- Tensor *tmp_2 = builder.get_runtime_graph()->addTensor(std::move(scratchpad_tensor));
-
- data_type = DataType::FLOAT32;
-
- scratchpad_tensor = std::make_unique<Tensor>(data_type, Shape({}), nullptr);
- scratchpad_tensor->set_data_buffer(nullptr);
- Tensor *tmp_3 = builder.get_runtime_graph()->addTensor(std::move(scratchpad_tensor));
-
- scratchpad_tensor = std::make_unique<Tensor>(data_type, Shape({}), nullptr);
- scratchpad_tensor->set_data_buffer(nullptr);
- Tensor *tmp_4 = builder.get_runtime_graph()->addTensor(std::move(scratchpad_tensor));
-
- scratchpad_tensor = std::make_unique<Tensor>(data_type, Shape({}), nullptr);
- scratchpad_tensor->set_data_buffer(nullptr);
- Tensor *tmp_5 = builder.get_runtime_graph()->addTensor(std::move(scratchpad_tensor));
-
- scratchpad_tensor = std::make_unique<Tensor>(data_type, Shape({}), nullptr);
- scratchpad_tensor->set_data_buffer(nullptr);
- Tensor *tmp_6 = builder.get_runtime_graph()->addTensor(std::move(scratchpad_tensor));
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsSVDFOptions();
-
- SVDFParams params{};
- params.activation = luci_actfunc(options->fused_activation_function);
- params.svdf_rank = options->rank;
- params.asymmetric_quantize_inputs = options->asymmetric_quantize_inputs;
-
- return std::make_unique<kernels::SVDF>(input, feature, time, bias, input_activation_state, output,
- tmp, tmp_1, tmp_2, tmp_3, tmp_4, tmp_5, tmp_6, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Shape.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Shape.cpp
deleted file mode 100644
index 69a727fae..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Shape.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Shape.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleShape(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 1);
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsShapeOptions();
-
- ShapeParams shape_params{};
- shape_params.out_type = luci_datatype(options->out_type);
-
- return std::make_unique<kernels::ShapeKernel>(input, output, shape_params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Slice.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Slice.cpp
deleted file mode 100644
index e28742b3f..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Slice.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Slice.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleSlice(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 3);
-
- const Tensor *input = inputs.at(0);
- const Tensor *begin = inputs.at(1);
- const Tensor *size = inputs.at(2);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::Slice>(input, begin, size, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Softmax.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Softmax.cpp
deleted file mode 100644
index 1957a76f4..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Softmax.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Softmax.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleSoftmax(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 1);
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsSoftmaxOptions();
-
- SoftmaxParams params{};
- params.beta = options->beta;
-
- return std::make_unique<kernels::Softmax>(input, output, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/SpaceToBatchND.cpp b/onert-micro/luci-interpreter/src/loader/nodes/SpaceToBatchND.cpp
deleted file mode 100644
index c5553c63e..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/SpaceToBatchND.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/SpaceToBatchND.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleSpaceToBatchND(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 3);
-
- const Tensor *input = inputs.at(0);
- const Tensor *block_shape = inputs.at(1);
- const Tensor *paddings = inputs.at(2);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::SpaceToBatchND>(input, block_shape, paddings, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/SpaceToDepth.cpp b/onert-micro/luci-interpreter/src/loader/nodes/SpaceToDepth.cpp
deleted file mode 100644
index 156976a63..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/SpaceToDepth.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/SpaceToDepth.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleSpaceToDepth(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 1);
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsSpaceToDepthOptions();
-
- SpaceToDepthParams params{};
- params.block_size = options->block_size;
-
- return std::make_unique<kernels::SpaceToDepth>(input, output, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Split.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Split.cpp
deleted file mode 100644
index ecec1cbca..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Split.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Split.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleSplit(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
-
- const Tensor *axis = inputs.at(0);
- const Tensor *input = inputs.at(1);
- std::vector<Tensor *> output_tensors(outputs.size());
-
- for (uint32_t i = 0; i < outputs.size(); ++i)
- {
- output_tensors[i] = outputs.at(i).first;
- }
-
- // NOTE 'num_splits' attribute is ignored.
- return std::make_unique<kernels::Split>(axis, input, std::move(output_tensors));
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/SplitV.cpp b/onert-micro/luci-interpreter/src/loader/nodes/SplitV.cpp
deleted file mode 100644
index a4c0ae28d..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/SplitV.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/SplitV.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleSplitV(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 3);
-
- const Tensor *input = inputs.at(0);
- const Tensor *sizes_data = inputs.at(1);
- const Tensor *axis = inputs.at(2);
- std::vector<Tensor *> output_tensors(outputs.size());
-
- for (uint32_t i = 0; i < outputs.size(); ++i)
- {
- output_tensors[i] = outputs.at(i).first;
- }
-
- // NOTE 'num_splits' attribute is ignored.
- return std::make_unique<kernels::SplitV>(input, sizes_data, axis, std::move(output_tensors));
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Sqrt.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Sqrt.cpp
deleted file mode 100644
index 3eaf2343d..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Sqrt.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Sqrt.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleSqrt(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 1);
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::Sqrt>(input, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Square.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Square.cpp
deleted file mode 100644
index 1afc6ccde..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Square.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Square.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleSquare(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 1);
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::Square>(input, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/SquaredDifference.cpp b/onert-micro/luci-interpreter/src/loader/nodes/SquaredDifference.cpp
deleted file mode 100644
index 0a5ba788d..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/SquaredDifference.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/SquaredDifference.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleSquaredDifference(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
-
- const Tensor *input1 = inputs.at(0);
- const Tensor *input2 = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::SquaredDifference>(input1, input2, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Squeeze.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Squeeze.cpp
deleted file mode 100644
index 4f0c265eb..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Squeeze.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Squeeze.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleSqueeze(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 1);
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsSqueezeOptions();
-
- SqueezeParams params{};
- params.squeeze_dims = options->squeeze_dims;
-
- return std::make_unique<kernels::Squeeze>(input, output, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/StridedSlice.cpp b/onert-micro/luci-interpreter/src/loader/nodes/StridedSlice.cpp
deleted file mode 100644
index c0a53fc94..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/StridedSlice.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/StridedSlice.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleStridedSlice(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 4);
-
- const Tensor *input = inputs.at(0);
- const Tensor *begin = inputs.at(1);
- const Tensor *end = inputs.at(2);
- const Tensor *strides = inputs.at(3);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsStridedSliceOptions();
-
- StridedSliceParams params{};
- params.begin_mask = options->begin_mask;
- params.ellipsis_mask = options->ellipsis_mask;
- params.end_mask = options->end_mask;
- params.new_axis_mask = options->new_axis_mask;
- params.shrink_axis_mask = options->shrink_axis_mask;
-
- return std::make_unique<kernels::StridedSlice>(input, begin, end, strides, output, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Sub.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Sub.cpp
deleted file mode 100644
index 79c773bdf..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Sub.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Sub.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleSub(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
-
- const Tensor *input1 = inputs.at(0);
- const Tensor *input2 = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsSubOptions();
-
- SubParams params{};
- params.activation = luci_actfunc(options->fused_activation_function);
-
- return std::make_unique<kernels::Sub>(input1, input2, output, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Tanh.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Tanh.cpp
deleted file mode 100644
index f4aff4c57..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Tanh.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Tanh.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleTanh(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 1);
- const Tensor *input = inputs.at(0);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::Tanh>(input, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Transpose.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Transpose.cpp
deleted file mode 100644
index 83b466d6a..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Transpose.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Transpose.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleTranspose(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 2);
-
- const Tensor *input = inputs.at(0);
- const Tensor *perm = inputs.at(1);
- Tensor *output = outputs.at(0);
-
- return std::make_unique<kernels::Transpose>(input, perm, output);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/TransposeConv.cpp b/onert-micro/luci-interpreter/src/loader/nodes/TransposeConv.cpp
deleted file mode 100644
index 06ee63eb1..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/TransposeConv.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/TransposeConv.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleTransposeConv(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index,
- KernelBuilder &builder)
-{
- assert(inputs.size() == 4);
-
- const Tensor *input_sizes = inputs.at(0);
- const Tensor *filter = inputs.at(1);
- const Tensor *out_backprop = inputs.at(2);
- const Tensor *bias = inputs.at(3);
- Tensor *output = outputs.at(0);
-
- DataType scratch_data_type =
- input_sizes->element_type() == DataType::S16 ? DataType::S64 : DataType::S32;
-
- auto scratch_tensor = std::make_unique<Tensor>(scratch_data_type, Shape({}), nullptr);
- scratch_tensor->set_data_buffer(nullptr);
- Tensor *tmp = builder.get_runtime_graph()->addTensor(std::move(scratch_tensor));
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsTransposeConvOptions();
-
- TransposeConvParams params{};
- params.padding = luci_padding(options->padding);
- params.stride_height = options->stride_h;
- params.stride_width = options->stride_w;
-
- return std::make_unique<kernels::TransposeConv>(input_sizes, filter, out_backprop, bias, output,
- tmp, params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/UnidirectionalSequenceLSTM.cpp b/onert-micro/luci-interpreter/src/loader/nodes/UnidirectionalSequenceLSTM.cpp
deleted file mode 100644
index b66e53fb7..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/UnidirectionalSequenceLSTM.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/UnidirectionalSequenceLSTM.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel>
-build_kernel_CircleUnidirectionalSequenceLSTM(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 24);
- const Tensor *input = inputs.at(0);
- const Tensor *input_to_input_weights = inputs.at(1);
- const Tensor *input_to_forget_weights = inputs.at(2);
- const Tensor *input_to_cell_weights = inputs.at(3);
- const Tensor *input_to_output_weights = inputs.at(4);
-
- const Tensor *recurrent_to_input_weights = inputs.at(5);
- const Tensor *recurrent_to_forget_weights = inputs.at(6);
- const Tensor *recurrent_to_cell_weights = inputs.at(7);
- const Tensor *recurrent_to_output_weights = inputs.at(8);
-
- const Tensor *cell_to_input_weights = inputs.at(9);
- const Tensor *cell_to_forget_weights = inputs.at(10);
- const Tensor *cell_to_output_weights = inputs.at(11);
-
- const Tensor *input_gate_bias = inputs.at(12);
- const Tensor *forget_gate_bias = inputs.at(13);
- const Tensor *cell_gate_bias = inputs.at(14);
- const Tensor *output_gate_bias = inputs.at(15);
-
- const Tensor *projection_weights = inputs.at(16);
- const Tensor *projection_bias = inputs.at(17);
-
- Tensor *output_state = const_cast<Tensor *>(inputs.at(18));
- Tensor *cell_state = const_cast<Tensor *>(inputs.at(19));
-
- const Tensor *input_layer_norm_coefficients = inputs.at(20);
- const Tensor *forget_layer_norm_coefficients = inputs.at(21);
- const Tensor *cell_layer_norm_coefficients = inputs.at(22);
- const Tensor *output_layer_norm_coefficients = inputs.at(23);
- Tensor *output = outputs.at(0);
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsUnidirectionalSequenceLSTMOptions();
-
- UnidirectionalSequenceLSTMParams params{};
- params.activation = luci_actfunc(options->fused_activation_function);
- params.cell_clip = options->cell_clip;
- params.proj_clip = options->proj_clip;
- params.time_major = options->time_major;
- params.asymmetric_quantize_inputs = options->asymmetric_quantize_inputs;
-
- // scratch pad tensor
- const bool is_integer = input->element_type() == DataType::S8;
- bool use_layer_norm = (forget_layer_norm_coefficients != nullptr);
-
- if (is_integer)
- {
- if (not use_layer_norm)
- {
- params.intermediate_affine_quant =
- builder.get_runtime_graph()->getIntermediateAffineQuantizations();
-
- // For integer LSTM need 4 16-bit buffer with size n_batch * n_cell
- // and 1 8-bit buffer with size n_batch * n_cell
- auto tmp_1 = std::make_unique<Tensor>(DataType::S16, Shape({}), nullptr);
- tmp_1->set_data_buffer(nullptr);
- outputs.push_back(builder.get_runtime_graph()->addTensor(std::move(tmp_1)));
-
- auto tmp_2 = std::make_unique<Tensor>(DataType::S16, Shape({}), nullptr);
- tmp_2->set_data_buffer(nullptr);
- outputs.push_back(builder.get_runtime_graph()->addTensor(std::move(tmp_2)));
-
- auto tmp_3 = std::make_unique<Tensor>(DataType::S16, Shape({}), nullptr);
- tmp_3->set_data_buffer(nullptr);
- outputs.push_back(builder.get_runtime_graph()->addTensor(std::move(tmp_3)));
-
- auto tmp_4 = std::make_unique<Tensor>(DataType::S16, Shape({}), nullptr);
- tmp_4->set_data_buffer(nullptr);
- outputs.push_back(builder.get_runtime_graph()->addTensor(std::move(tmp_4)));
-
- auto tmp_5 = std::make_unique<Tensor>(
- DataType::S8, Shape({}),
- builder.get_runtime_graph()->getIntermediateAffineQuantizations()[0]);
- tmp_5->set_data_buffer(nullptr);
- outputs.push_back(builder.get_runtime_graph()->addTensor(std::move(tmp_5)));
- }
- else
- {
- // TODO: support float
- assert(false && "Not supported now");
- }
- }
- else
- {
- // NOTE provide more scratch pads if support hybrid or integer
- auto sp_output_state =
- std::make_unique<Tensor>(output_state->element_type(), Shape({}), nullptr);
- sp_output_state->set_data_buffer(nullptr);
- outputs.push_back(builder.get_runtime_graph()->addTensor(std::move(sp_output_state)));
-
- auto sp_cell_state = std::make_unique<Tensor>(cell_state->element_type(), Shape({}), nullptr);
- sp_cell_state->set_data_buffer(nullptr);
- outputs.push_back(builder.get_runtime_graph()->addTensor(std::move(sp_cell_state)));
-
- auto sp_3 = std::make_unique<Tensor>(input->element_type(), Shape({}), nullptr);
- sp_3->set_data_buffer(nullptr);
- outputs.push_back(builder.get_runtime_graph()->addTensor(std::move(sp_3)));
- }
-
- outputs.push_back(output_state);
- outputs.push_back(cell_state);
-
- return std::make_unique<kernels::UnidirectionalSequenceLSTM>(
- input, input_to_input_weights, input_to_forget_weights, input_to_cell_weights,
- input_to_output_weights, recurrent_to_input_weights, recurrent_to_forget_weights,
- recurrent_to_cell_weights, recurrent_to_output_weights, cell_to_input_weights,
- cell_to_forget_weights, cell_to_output_weights, input_gate_bias, forget_gate_bias,
- cell_gate_bias, output_gate_bias, projection_weights, projection_bias,
- input_layer_norm_coefficients, forget_layer_norm_coefficients, cell_layer_norm_coefficients,
- output_layer_norm_coefficients, std::move(outputs), params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/loader/nodes/Unpack.cpp b/onert-micro/luci-interpreter/src/loader/nodes/Unpack.cpp
deleted file mode 100644
index 7f067f474..000000000
--- a/onert-micro/luci-interpreter/src/loader/nodes/Unpack.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Builders.h"
-
-#include "kernels/Unpack.h"
-
-namespace luci_interpreter
-{
-
-std::unique_ptr<Kernel> build_kernel_CircleUnpack(std::vector<const Tensor *> &&inputs,
- std::vector<Tensor *> &&outputs,
- const uint32_t op_index, KernelBuilder &builder)
-{
- assert(inputs.size() == 1);
-
- const Tensor *input = inputs.at(0);
- std::vector<Tensor *> output_tensors(outputs.size());
-
- for (uint32_t i = 0; i < outputs.size(); ++i)
- {
- output_tensors[i] = outputs.at(i);
- }
-
- circle::OperatorT oper_t;
- builder.get_circle_reader()->operators()[op_index]->UnPackTo(&oper_t);
- const auto *options = oper_t.builtin_options.AsUnpackOptions();
-
- UnpackParams params{};
- params.axis = options->axis;
-
- // NOTE 'num' attribute is ignored.
- return std::make_unique<kernels::Unpack>(input, std::move(output_tensors), params);
-}
-
-} // namespace luci_interpreter
diff --git a/onert-micro/standalone/CMakeLists.txt b/onert-micro/standalone/CMakeLists.txt
index 2dd7ef12d..e8495974c 100644
--- a/onert-micro/standalone/CMakeLists.txt
+++ b/onert-micro/standalone/CMakeLists.txt
@@ -3,8 +3,12 @@ project(luci_interpreter_micro_standalone)
include(${NNAS_ROOT}/infra/onert-micro/utils.cmake)
-nnas_find_package(FlatBuffersSource EXACT 2.0 QUIET)
-include_directories(${FlatBuffersSource_DIR}/include)
+if (NOT ${NOT_BUILD_EXTERNALS})
+ nnas_find_package(FlatBuffersSource EXACT 2.0 QUIET)
+ include_directories(${FlatBuffersSource_DIR}/include)
+else()
+ include_directories(${FlatBuffersSource_DIR})
+endif()
# TODO: fix luci/plan for new luci-micro without luci/IR
add_subdirectory(${NNAS_PROJECT_SOURCE_DIR}/onert-micro/luci-interpreter ${CMAKE_CURRENT_BINARY_DIR}/luci-interpreter)
diff --git a/packaging/ABSEIL.tar.gz b/packaging/ABSEIL.tar.gz
index dc7aab548..1d92825b5 100644
--- a/packaging/ABSEIL.tar.gz
+++ b/packaging/ABSEIL.tar.gz
Binary files differ
diff --git a/packaging/FLATBUFFERS-2.0.tar.gz b/packaging/FLATBUFFERS-2.0.tar.gz
index 5e8a3361d..809aca01a 100644
--- a/packaging/FLATBUFFERS-2.0.tar.gz
+++ b/packaging/FLATBUFFERS-2.0.tar.gz
Binary files differ
diff --git a/packaging/nnfw.spec b/packaging/nnfw.spec
index 6f17cf94a..a972af30b 100644
--- a/packaging/nnfw.spec
+++ b/packaging/nnfw.spec
@@ -1,6 +1,6 @@
Name: nnfw
Summary: nnfw
-Version: 1.22.1
+Version: 1.25.0
Release: 1
Group: Development
License: Apache-2.0 and MIT and BSD-2-Clause and MPL-2.0
@@ -31,12 +31,16 @@ Source3018: XNNPACK.tar.gz
Source3019: FLATBUFFERS-2.0.tar.gz
%{!?build_type: %define build_type Release}
-%{!?npud_build: %define npud_build 0}
+%{!?npud_build: %define npud_build 1}
%{!?trix_support: %define trix_support 1}
+%{!?odc_build: %define odc_build 1}
%{!?coverage_build: %define coverage_build 0}
%{!?test_build: %define test_build 0}
%{!?extra_option: %define extra_option %{nil}}
-%{!?config_support: %define config_support 0}
+%{!?config_support: %define config_support 1}
+# Define nproc on gbs build option if you want to set number of build threads manually (ex. CI/CD infra)
+%define build_jobs %{?!nproc:%{?_smp_mflags}%{?!_smp_mflags:-j4}}%{?nproc:-j%nproc}
+%{!?nproc: %define nproc %{?!jobs:4}%{?jobs}}
%if %{coverage_build} == 1
# Coverage test requires debug build runtime
@@ -84,6 +88,14 @@ Requires: %{name}-devel = %{version}-%{release}
%description plugin-devel
NNFW development package for backend plugin developer
+%if %{odc_build} == 1
+%package odc
+Summary: NNFW On-Device Compilation Package
+
+%description odc
+NNFW package for on-device compilation
+%endif # odc_build
+
%package minimal-app
Summary: Minimal test binary for VD manual test
@@ -129,12 +141,15 @@ NPU daemon for optimal management of NPU hardware
%define install_path %{buildroot}%{install_dir}
%define nnfw_workspace build
%define build_env NNFW_WORKSPACE=%{nnfw_workspace}
+%define nncc_workspace build/nncc
+%define nncc_env NNCC_WORKSPACE=%{nncc_workspace}
+%define overlay_path %{nnfw_workspace}/overlay
# Path to install test bin and scripts (test script assumes path Product/out)
# TODO Share path with release package
%define test_install_home /opt/usr/nnfw-test
%define test_install_dir %{test_install_home}/Product/out
-%define test_install_path %{buildroot}%{test_install_dir}
+%define test_install_path %{buildroot}/%{test_install_dir}
# Set option for test build (and coverage test build)
%define option_test -DENABLE_TEST=OFF
@@ -148,22 +163,19 @@ NPU daemon for optimal management of NPU hardware
# Set option for configuration
%define option_config %{nil}
-%if %{npud_build} == 1
%if %{config_support} == 1
+%if %{npud_build} == 1
# ENVVAR_NPUD_CONFIG: Use environment variable for npud configuration and debug
-%define option_config -DBUILD_NPUD=ON -DENVVAR_NPUD_CONFIG=ON
-%else
-%define option_config -DBUILD_NPUD=ON -DENVVAR_NPUD_CONFIG=OFF
-%endif # config_support
-%else
-%define option_config -DBUILD_NPUD=OFF
+%define option_config -DENVVAR_NPUD_CONFIG=ON
%endif # npud_build
+%endif # config_support
%if %{coverage_build} == 1
%define option_coverage -DENABLE_COVERAGE=ON
%endif # coverage_build
-%define build_options -DCMAKE_BUILD_TYPE=%{build_type} -DTARGET_ARCH=%{target_arch} -DTARGET_OS=tizen -DBUILD_MINIMAL_SAMPLE=ON \\\
+%define build_options -DCMAKE_BUILD_TYPE=%{build_type} -DTARGET_ARCH=%{target_arch} -DTARGET_OS=tizen \\\
+ -DEXTERNALS_BUILD_THREAD=%{nproc} -DBUILD_MINIMAL_SAMPLE=ON -DNNFW_OVERLAY_DIR=$(pwd)/%{overlay_path} \\\
%{option_test} %{option_coverage} %{option_config} %{extra_option}
%prep
@@ -193,9 +205,24 @@ tar -xf %{SOURCE3019} -C ./externals
%build
%ifarch arm armv7l armv7hl aarch64 x86_64 %ix86
+# nncc build
+%if %{odc_build} == 1
+%{nncc_env} ./nncc configure -DBUILD_GTEST=OFF -DENABLE_TEST=OFF -DEXTERNALS_BUILD_THREADS=%{nproc} -DCMAKE_BUILD_TYPE=%{build_type} -DTARGET_OS=tizen \
+ -DCMAKE_INSTALL_PREFIX=$(pwd)/%{overlay_path} \
+ -DBUILD_WHITELIST="luci;foder;pepper-csv2vec;loco;locop;logo;logo-core;mio-circle06;luci-compute;oops;hermes;hermes-std;angkor;pp;pepper-strcast;pepper-str"
+%{nncc_env} ./nncc build %{build_jobs}
+cmake --install %{nncc_workspace}
+%endif # odc_build
+
+# install angkor TensorIndex and oops InternalExn header (TODO: Remove this)
+mkdir -p %{overlay_path}/include/nncc/core/ADT/tensor
+mkdir -p %{overlay_path}/include/oops
+cp compiler/angkor/include/nncc/core/ADT/tensor/Index.h %{overlay_path}/include/nncc/core/ADT/tensor
+cp compiler/oops/include/oops/InternalExn.h %{overlay_path}/include/oops
+
# runtime build
%{build_env} ./nnfw configure %{build_options}
-%{build_env} ./nnfw build -j4
+%{build_env} ./nnfw build %{build_jobs}
# install in workspace
# TODO Set install path
%{build_env} ./nnfw install
@@ -258,6 +285,13 @@ install -m 0644 ./tests/scripts/build_path.txt %{buildroot}%{test_install_dir}/t
%endif # coverage_build
%endif # test_build
+%if %{odc_build} == 1
+mkdir -p %{buildroot}%{_libdir}/nnfw/odc
+install -m 644 %{overlay_path}/lib/libluci*.so %{buildroot}%{_libdir}/nnfw/odc
+install -m 644 %{overlay_path}/lib/libloco*.so %{buildroot}%{_libdir}/nnfw/odc
+install -m 644 build/out/lib/nnfw/odc/*.so %{buildroot}%{_libdir}/nnfw/odc
+%endif # odc_build
+
%if %{npud_build} == 1
install -m 755 build/out/bin/npud %{buildroot}%{_bindir}
@@ -325,6 +359,16 @@ install -m 755 build/out/npud-gtest/* %{test_install_path}/npud-gtest
%endif # arm armv7l armv7hl aarch64 x86_64 %ix86
%endif # npud_build
+%if %{odc_build} == 1
+%files odc
+%manifest %{name}.manifest
+%defattr(-,root,root,-)
+%ifarch arm armv7l armv7hl aarch64 x86_64 %ix86
+%dir %{_libdir}/nnfw/odc
+%{_libdir}/nnfw/odc/*
+%endif # arm armv7l armv7hl aarch64 x86_64 %ix86
+%endif # odc_build
+
%changelog
* Thu Mar 15 2018 Chunseok Lee <chunseok.lee@samsung.com>
- Initial spec file for nnfw
diff --git a/res/CircleSchema/0.5/circle_schema.fbs b/res/CircleSchema/0.5/circle_schema.fbs
new file mode 100644
index 000000000..e0a0dc476
--- /dev/null
+++ b/res/CircleSchema/0.5/circle_schema.fbs
@@ -0,0 +1,1338 @@
+// Copyright (c) 2019~2023 Samsung Electronics Co., Ltd. All Rights Reserved
+// Copyright 2017 The TensorFlow Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Revision History
+//
+// Version Major.Minor
+//
+// Major version is schema version.
+// We keep schema version if it is compatible
+// Minor version is for human communication
+// It will not be stored in circle model.
+//
+// Version 0.0: Initial version. Based on TensorFlow Lite v1.13.1 schema.
+// Version 0.1: Based on TF v2.2-rc2 + more (from TensorFlow `56d281c`)
+// `BATCH_MATMUL` operator, `FLOAT64` tensor type,
+// `asymmetric_quantize_inputs` for several operator options
+// Version 0.2: BCQ_GATHER and BCQ_FULLY_CONNECTED are added.
+// Version 0.3: SHUFFLED16x1FLOAT32 is added.
+// Version 0.4: Base up to TensorFlow Lite v2.7.0 schema.
+// Version 0.5: Base up to TensorFlow Lite v2.10.1 schema.
+
+namespace circle;
+
+// This corresponds to the version.
+file_identifier "CIR0";
+// File extension of any written files.
+file_extension "circle";
+
+// IMPORTANT: All new members of tables, enums and unions must be added at the
+// end to ensure backwards compatibility.
+
+// The type of data stored in a tensor.
+enum TensorType : byte {
+ FLOAT32 = 0,
+ FLOAT16 = 1,
+ INT32 = 2,
+ UINT8 = 3,
+ INT64 = 4,
+ STRING = 5,
+ BOOL = 6,
+ INT16 = 7,
+ COMPLEX64 = 8,
+ INT8 = 9,
+ FLOAT64 = 10,
+ COMPLEX128 = 11,
+ UINT64 = 12,
+ // Experimental: Resource and variant types are experimental, that are subject
+ // to change. Do not implement custom kernels using resource & variant types
+ // now.
+ RESOURCE = 13,
+ VARIANT = 14,
+ UINT32 = 15,
+ UINT16 = 16
+}
+
+// Custom quantization parameters for experimenting with new quantization
+// techniques.
+table CustomQuantization {
+ custom:[ubyte] (force_align: 16);
+}
+
+// Represents a specific quantization technique's parameters.
+union QuantizationDetails {
+ CustomQuantization,
+}
+
+// Parameters for converting a quantized tensor back to float.
+table QuantizationParameters {
+ // These four parameters are the asymmetric linear quantization parameters.
+ // Given a quantized value q, the corresponding float value f should be:
+ // f = scale * (q - zero_point)
+ // For other quantization types, the QuantizationDetails below is used.
+ min:[float]; // For importing back into tensorflow.
+ max:[float]; // For importing back into tensorflow.
+ scale:[float]; // For dequantizing the tensor's values.
+ zero_point:[long];
+
+ // If this is not none, the other quantization parameters (i.e. min, max,
+ // scale, zero_point fields above) are ignored and the value of the
+ // QuantizationDetails union should be used.
+ details:QuantizationDetails;
+
+ // Specifies the dimension of the Tensor's shape that the scales and
+ // zero_points correspond to. For example, a tensor t, with dims=[4, 3, 2, 1]
+ // with quantization params:
+ // scale=[1.0, 2.0, 3.0], zero_point=[1, 2, 3], quantization_dimension=1
+ // will be quantized across the second dimension of t.
+ // t[:, 0, :, :] will have scale[0]=1.0, zero_point[0]=1
+ // t[:, 1, :, :] will have scale[1]=2.0, zero_point[0]=2
+ // t[:, 2, :, :] will have scale[2]=3.0, zero_point[0]=3
+ quantized_dimension:int;
+}
+
+// Sparse tensors.
+// We use a modification of the TACO format.
+// Reference: http://tensor-compiler.org/kjolstad-oopsla17-tensor-compiler.pdf
+//
+// To encode a conceptual n-dimensional dense tensor with dims (d0, ..., dn-1),
+// potentially with a k-dimensional block (0 <= k <= n) with dims
+// (dn, ..., dn+k-1), the format needs to specify:
+// 1. In what order to traverse these dimensions. For example, to store a 2-D
+// matrix in row major order, the traversal order would be (d0, d1),
+// whereas to store it in column major order, the traversal order would be
+// (d1, d0). If the 2-D matrix has a 2-D inner block, the traversal order
+// could be (d0, d1, d2, d3).
+// 2. How each block dimension in (dn, ..., dn+k-1) maps to the original
+// tensor dimension in (d0, ..., dn-1).
+// 3. In the traversal order defined above, the format (dense vs. sparse) and
+// index metadata for each dimension. For a dense dimension, this is just
+// the size of that dimension. For a sparse dimension, it's the same as
+// the compressed index defined in the Compressed Sparse Row (CSR) format.
+// (http://scipy-lectures.org/advanced/scipy_sparse/csr_matrix.html)
+
+// The storage type for a dimension. Currently we support:
+// 1. DENSE: each coordinate in this dimension is stored implicitly.
+// 2. SPARSE_CSR: only the coordinates with non-zero elements are stored. The
+// compression technique is the same what CSR uses.
+// More types like a sparse dimension with a different compression technique
+// could be added to the list in the future.
+enum DimensionType : byte {
+ DENSE = 0,
+ SPARSE_CSR = 1,
+}
+
+table Int32Vector {
+ values:[int];
+}
+
+table Uint16Vector {
+ values:[ushort] (force_align: 4);
+}
+
+table Uint8Vector {
+ values:[ubyte] (force_align: 4);
+}
+
+// Variable-typed buffer to store the index metadata for a sparse dimension.
+// The widest type is Int32 instead of UInt32 because tensor's shape is a int32
+// vector. We don't want the per-dimensional index to overflow that range.
+union SparseIndexVector {
+ Int32Vector,
+ Uint16Vector,
+ Uint8Vector
+}
+
+table DimensionMetadata {
+ // Whether a dimension is dense or sparse.
+ format:DimensionType;
+ // Index metadata used for a dimension.
+ // - If format is DimensionType.DENSE then we use the dense_size field to
+ // store the size of that dimension. Each index in that dimension is
+ // stored implicitly.
+ // - If format is DimensionType.SPARSE_CSR then we use array_segments and
+ // array_indices to encode that dimension. array_segments represents how
+ // to segment the indices array, each segment corresponds to one element
+ // in the previous dimension. array_indices represents the index of the
+ // non-zero elements within this dimension (as those in the CSR matrix
+ // format, where the first array is row pointers and the second array is
+ // column indices).
+ dense_size:int;
+ array_segments:SparseIndexVector;
+ array_indices:SparseIndexVector;
+}
+
+// Parameters to encode a sparse TfLite tensor.
+table SparsityParameters {
+ // The traversal order of the dimensions defined in the `shape` field of the
+ // conceptual dense tensor. For a n-dimensional tensors with dims (d0, d1,
+ // ..., dn-1),
+ // - if not block sparse, the traversal_order is just a permutation of (d0,
+ // ..., dn-1). For example, a 2-D matrix stored in row-major order would
+ // have traversal_order = (d0, d1).
+ // - if block sparse with a k-dimensional block (0 <= k <= n), the
+ // traversal_order has n + k elements. The first n elements are still a
+ // permutation of (d0, ..., dn-1). The lask k elements are a permutation
+ // of (dn, ..., dn+k-1), defining how to traverse a block internally. For
+ // example, a 2-D matrix with 2-D blocks, both stored in row-major order
+ // would have traversal_order = (d0, d1, d2, d3).
+ traversal_order:[int];
+ // For an n-dimensional tensor with a k-dimensional block (0 <= k <= n),
+ // stores how a block dimension in (dn, ..., dn+k-1) maps to the original
+ // tensor dimension in (d0, ..., dn).
+ // It's stored in the order of (dn, ..., dn+k-1).
+ // If not block-sparse, this field is NULL.
+ block_map:[int];
+ // In the traversal order defined above, the metadata needed for
+ // each dimension to locate the non-zero values in the original dense tensor.
+ // The size of the dim_metadata array = the size of the traversal_order array
+ // = n + k.
+ dim_metadata:[DimensionMetadata];
+}
+
+table Tensor {
+ // The tensor shape. The meaning of each entry is operator-specific but
+ // builtin ops use: [batch size, height, width, number of channels] (That's
+ // Tensorflow's NHWC).
+ shape:[int];
+ type:TensorType;
+ // An index that refers to the buffers table at the root of the model. Or,
+ // if there is no data buffer associated (i.e. intermediate results), then
+ // this is 0 (which refers to an always existent empty buffer).
+ //
+ // The data_buffer itself is an opaque container, with the assumption that the
+ // target device is little-endian. In addition, all builtin operators assume
+ // the memory is ordered such that if `shape` is [4, 3, 2], then index
+ // [i, j, k] maps to data_buffer[i*3*2 + j*2 + k].
+ buffer:uint;
+ name:string; // For debugging and importing back into tensorflow.
+ quantization:QuantizationParameters; // Optional.
+
+ is_variable:bool = false;
+
+ // Parameters to encode a sparse tensor. See the example in
+ // tensorflow/lite/testdata/sparse_tensor.json.
+ sparsity:SparsityParameters; // Optional.
+
+ // Encodes `shape` with unknown dimensions. Unknown dimensions are
+ // represented with -1.
+ shape_signature:[int]; // Optional.
+
+ // If false, the rank or the number of tensor dimensions is unknown.
+ // If false, "shape" must be [].
+ has_rank: bool = false;
+}
+
+// A list of builtin operators. Builtin operators are slightly faster than custom
+// ones, but not by much. Moreover, while custom operators accept an opaque
+// object containing configuration parameters, builtins have a predetermined
+// set of acceptable options.
+// LINT.IfChange
+enum BuiltinOperator : int32 {
+ BCQ_GATHER = -4,
+ BCQ_FULLY_CONNECTED = -3,
+ INSTANCE_NORM = -2,
+ ADD = 0,
+ AVERAGE_POOL_2D = 1,
+ CONCATENATION = 2,
+ CONV_2D = 3,
+ DEPTHWISE_CONV_2D = 4,
+ DEPTH_TO_SPACE = 5,
+ DEQUANTIZE = 6,
+ EMBEDDING_LOOKUP = 7,
+ FLOOR = 8,
+ FULLY_CONNECTED = 9,
+ HASHTABLE_LOOKUP = 10,
+ L2_NORMALIZATION = 11,
+ L2_POOL_2D = 12,
+ LOCAL_RESPONSE_NORMALIZATION = 13,
+ LOGISTIC = 14,
+ LSH_PROJECTION = 15,
+ LSTM = 16,
+ MAX_POOL_2D = 17,
+ MUL = 18,
+ RELU = 19,
+ // NOTE(aselle): RELU_N1_TO_1 used to be called RELU1, but it was renamed
+ // since different model developers use RELU1 in different ways. Never
+ // create another op called RELU1.
+ RELU_N1_TO_1 = 20,
+ RELU6 = 21,
+ RESHAPE = 22,
+ RESIZE_BILINEAR = 23,
+ RNN = 24,
+ SOFTMAX = 25,
+ SPACE_TO_DEPTH = 26,
+ SVDF = 27,
+ TANH = 28,
+ CONCAT_EMBEDDINGS = 29,
+ SKIP_GRAM = 30,
+ CALL = 31,
+ CUSTOM = 32,
+ EMBEDDING_LOOKUP_SPARSE = 33,
+ PAD = 34,
+ UNIDIRECTIONAL_SEQUENCE_RNN = 35,
+ GATHER = 36,
+ BATCH_TO_SPACE_ND = 37,
+ SPACE_TO_BATCH_ND = 38,
+ TRANSPOSE = 39,
+ MEAN = 40,
+ SUB = 41,
+ DIV = 42,
+ SQUEEZE = 43,
+ UNIDIRECTIONAL_SEQUENCE_LSTM = 44,
+ STRIDED_SLICE = 45,
+ BIDIRECTIONAL_SEQUENCE_RNN = 46,
+ EXP = 47,
+ TOPK_V2 = 48,
+ SPLIT = 49,
+ LOG_SOFTMAX = 50,
+ // DELEGATE is a special op type for the operations which are delegated to
+ // other backends.
+ // WARNING: Experimental interface, subject to change
+ DELEGATE = 51,
+ BIDIRECTIONAL_SEQUENCE_LSTM = 52,
+ CAST = 53,
+ PRELU = 54,
+ MAXIMUM = 55,
+ ARG_MAX = 56,
+ MINIMUM = 57,
+ LESS = 58,
+ NEG = 59,
+ PADV2 = 60,
+ GREATER = 61,
+ GREATER_EQUAL = 62,
+ LESS_EQUAL = 63,
+ SELECT = 64,
+ SLICE = 65,
+ SIN = 66,
+ TRANSPOSE_CONV = 67,
+ SPARSE_TO_DENSE = 68,
+ TILE = 69,
+ EXPAND_DIMS = 70,
+ EQUAL = 71,
+ NOT_EQUAL = 72,
+ LOG = 73,
+ SUM = 74,
+ SQRT = 75,
+ RSQRT = 76,
+ SHAPE = 77,
+ POW = 78,
+ ARG_MIN = 79,
+ FAKE_QUANT = 80,
+ REDUCE_PROD = 81,
+ REDUCE_MAX = 82,
+ PACK = 83,
+ LOGICAL_OR = 84,
+ ONE_HOT = 85,
+ LOGICAL_AND = 86,
+ LOGICAL_NOT = 87,
+ UNPACK = 88,
+ REDUCE_MIN = 89,
+ FLOOR_DIV = 90,
+ REDUCE_ANY = 91,
+ SQUARE = 92,
+ ZEROS_LIKE = 93,
+ FILL = 94,
+ FLOOR_MOD = 95,
+ RANGE = 96,
+ RESIZE_NEAREST_NEIGHBOR = 97,
+ LEAKY_RELU = 98,
+ SQUARED_DIFFERENCE = 99,
+ MIRROR_PAD = 100,
+ ABS = 101,
+ SPLIT_V = 102,
+ UNIQUE = 103,
+ CEIL = 104,
+ REVERSE_V2 = 105,
+ ADD_N = 106,
+ GATHER_ND = 107,
+ COS = 108,
+ WHERE = 109,
+ RANK = 110,
+ ELU = 111,
+ REVERSE_SEQUENCE = 112,
+ MATRIX_DIAG = 113,
+ QUANTIZE = 114,
+ MATRIX_SET_DIAG = 115,
+ ROUND = 116,
+ HARD_SWISH = 117,
+ IF = 118,
+ WHILE = 119,
+ NON_MAX_SUPPRESSION_V4 = 120,
+ NON_MAX_SUPPRESSION_V5 = 121,
+ SCATTER_ND = 122,
+ SELECT_V2 = 123,
+ DENSIFY = 124,
+ SEGMENT_SUM = 125,
+ BATCH_MATMUL = 126,
+ PLACEHOLDER_FOR_GREATER_OP_CODES = 127,
+ CUMSUM = 128,
+ CALL_ONCE = 129,
+ BROADCAST_TO = 130,
+ RFFT2D = 131,
+ CONV_3D = 132,
+ IMAG=133,
+ REAL=134,
+ COMPLEX_ABS=135,
+ HASHTABLE = 136,
+ HASHTABLE_FIND = 137,
+ HASHTABLE_IMPORT = 138,
+ HASHTABLE_SIZE = 139,
+ REDUCE_ALL = 140,
+ CONV_3D_TRANSPOSE = 141,
+ VAR_HANDLE = 142,
+ READ_VARIABLE = 143,
+ ASSIGN_VARIABLE = 144,
+ BROADCAST_ARGS = 145,
+ RANDOM_STANDARD_NORMAL = 146,
+ BUCKETIZE = 147,
+ RANDOM_UNIFORM = 148,
+ MULTINOMIAL = 149,
+ GELU = 150,
+ DYNAMIC_UPDATE_SLICE = 151,
+ RELU_0_TO_1 = 152,
+ UNSORTED_SEGMENT_PROD = 153,
+ UNSORTED_SEGMENT_MAX = 154,
+ UNSORTED_SEGMENT_SUM = 155,
+ ATAN2 = 156
+}
+// LINT.ThenChange(nnapi_linter/linter.proto)
+
+// Options for the builtin operators.
+union BuiltinOptions {
+ Conv2DOptions,
+ DepthwiseConv2DOptions,
+ ConcatEmbeddingsOptions,
+ LSHProjectionOptions,
+ Pool2DOptions,
+ SVDFOptions,
+ RNNOptions,
+ FullyConnectedOptions,
+ SoftmaxOptions,
+ ConcatenationOptions,
+ AddOptions,
+ L2NormOptions,
+ LocalResponseNormalizationOptions,
+ LSTMOptions,
+ ResizeBilinearOptions,
+ CallOptions,
+ ReshapeOptions,
+ SkipGramOptions,
+ SpaceToDepthOptions,
+ EmbeddingLookupSparseOptions,
+ MulOptions,
+ PadOptions,
+ GatherOptions,
+ BatchToSpaceNDOptions,
+ SpaceToBatchNDOptions,
+ TransposeOptions,
+ ReducerOptions,
+ SubOptions,
+ DivOptions,
+ SqueezeOptions,
+ SequenceRNNOptions,
+ StridedSliceOptions,
+ ExpOptions,
+ TopKV2Options,
+ SplitOptions,
+ LogSoftmaxOptions,
+ CastOptions,
+ DequantizeOptions,
+ MaximumMinimumOptions,
+ ArgMaxOptions,
+ LessOptions,
+ NegOptions,
+ PadV2Options,
+ GreaterOptions,
+ GreaterEqualOptions,
+ LessEqualOptions,
+ SelectOptions,
+ SliceOptions,
+ TransposeConvOptions,
+ SparseToDenseOptions,
+ TileOptions,
+ ExpandDimsOptions,
+ EqualOptions,
+ NotEqualOptions,
+ ShapeOptions,
+ PowOptions,
+ ArgMinOptions,
+ FakeQuantOptions,
+ PackOptions,
+ LogicalOrOptions,
+ OneHotOptions,
+ LogicalAndOptions,
+ LogicalNotOptions,
+ UnpackOptions,
+ FloorDivOptions,
+ SquareOptions,
+ ZerosLikeOptions,
+ FillOptions,
+ BidirectionalSequenceLSTMOptions,
+ BidirectionalSequenceRNNOptions,
+ UnidirectionalSequenceLSTMOptions,
+ FloorModOptions,
+ RangeOptions,
+ ResizeNearestNeighborOptions,
+ LeakyReluOptions,
+ SquaredDifferenceOptions,
+ MirrorPadOptions,
+ AbsOptions,
+ SplitVOptions,
+ UniqueOptions,
+ ReverseV2Options,
+ AddNOptions,
+ GatherNdOptions,
+ CosOptions,
+ WhereOptions,
+ RankOptions,
+ ReverseSequenceOptions,
+ MatrixDiagOptions,
+ QuantizeOptions,
+ MatrixSetDiagOptions,
+ HardSwishOptions,
+ IfOptions,
+ WhileOptions,
+ DepthToSpaceOptions,
+ NonMaxSuppressionV4Options,
+ NonMaxSuppressionV5Options,
+ ScatterNdOptions,
+ SelectV2Options,
+ DensifyOptions,
+ SegmentSumOptions,
+ BatchMatMulOptions,
+ CumsumOptions,
+ CallOnceOptions,
+ BroadcastToOptions,
+ Rfft2dOptions,
+ Conv3DOptions,
+ HashtableOptions,
+ HashtableFindOptions,
+ HashtableImportOptions,
+ HashtableSizeOptions,
+ VarHandleOptions,
+ ReadVariableOptions,
+ AssignVariableOptions,
+ RandomOptions,
+ BucketizeOptions,
+ GeluOptions,
+ DynamicUpdateSliceOptions,
+ UnsortedSegmentProdOptions,
+ UnsortedSegmentMaxOptions,
+ UnsortedSegmentSumOptions,
+ ATan2Options,
+ BCQGatherOptions = 252,
+ BCQFullyConnectedOptions = 253,
+ InstanceNormOptions = 254,
+}
+
+enum Padding : byte { SAME, VALID }
+
+enum ActivationFunctionType : byte {
+ NONE = 0,
+ RELU = 1,
+ RELU_N1_TO_1 = 2,
+ RELU6 = 3,
+ TANH = 4,
+ SIGN_BIT = 5,
+}
+
+table Conv2DOptions {
+ padding:Padding;
+ stride_w:int;
+ stride_h:int;
+ fused_activation_function:ActivationFunctionType;
+ dilation_w_factor:int = 1;
+ dilation_h_factor:int = 1;
+}
+
+// Options for both Conv3D and Conv3DTranspose.
+table Conv3DOptions {
+ padding:Padding;
+ stride_d:int;
+ stride_w:int;
+ stride_h:int;
+ fused_activation_function:ActivationFunctionType;
+ dilation_d_factor:int = 1;
+ dilation_w_factor:int = 1;
+ dilation_h_factor:int = 1;
+}
+
+table Pool2DOptions {
+ padding:Padding;
+ stride_w:int;
+ stride_h:int;
+ filter_width:int;
+ filter_height:int;
+ fused_activation_function:ActivationFunctionType;
+}
+
+table DepthwiseConv2DOptions {
+ // Parameters for DepthwiseConv version 1 or above.
+ padding:Padding;
+ stride_w:int;
+ stride_h:int;
+ // `depth_multiplier` is redundant. It's used by CPU kernels in
+ // TensorFlow 2.0 or below, but ignored in versions above.
+ // See comments in lite/c/builtin_op_data.h for more details.
+ depth_multiplier:int;
+ fused_activation_function:ActivationFunctionType;
+ // Parameters for DepthwiseConv version 2 or above.
+ dilation_w_factor:int = 1;
+ dilation_h_factor:int = 1;
+}
+
+table ConcatEmbeddingsOptions {
+ num_channels:int;
+ num_columns_per_channel:[int];
+ embedding_dim_per_channel:[int]; // This could be inferred from parameters.
+}
+
+enum LSHProjectionType: byte {
+ UNKNOWN = 0,
+ SPARSE = 1,
+ DENSE = 2,
+}
+
+table LSHProjectionOptions {
+ type: LSHProjectionType;
+}
+
+table SVDFOptions {
+ rank:int;
+ fused_activation_function:ActivationFunctionType;
+ // For weights-only quantization, use asymmetric quantization for non
+ // constant inputs at evaluation time.
+ asymmetric_quantize_inputs:bool;
+}
+
+// An implementation of TensorFlow RNNCell.
+table RNNOptions {
+ fused_activation_function:ActivationFunctionType;
+ asymmetric_quantize_inputs:bool;
+}
+
+// An implementation of TensorFlow dynamic_rnn with RNNCell.
+table SequenceRNNOptions {
+ time_major:bool;
+ fused_activation_function:ActivationFunctionType;
+ asymmetric_quantize_inputs:bool;
+}
+
+// An implementation of TensorFlow bidrectional_dynamic_rnn with RNNCell.
+table BidirectionalSequenceRNNOptions {
+ time_major:bool;
+ fused_activation_function:ActivationFunctionType;
+ merge_outputs: bool;
+ asymmetric_quantize_inputs:bool;
+}
+
+enum FullyConnectedOptionsWeightsFormat: byte {
+ DEFAULT = 0,
+ SHUFFLED4x16INT8 = 1,
+ SHUFFLED16x1FLOAT32 = 127
+}
+
+// An implementation of TensorFlow fully_connected (a.k.a Dense) layer.
+table FullyConnectedOptions {
+ // Parameters for FullyConnected version 1 or above.
+ fused_activation_function:ActivationFunctionType;
+
+ // Parameters for FullyConnected version 2 or above.
+ weights_format:FullyConnectedOptionsWeightsFormat = DEFAULT;
+
+ // Parameters for FullyConnected version 5 or above.
+ // If set to true, then the number of dimension is preserved. Furthermore,
+ // all but the last dimension of the input and output shapes will be equal.
+ keep_num_dims: bool;
+
+ // Parameters for FullyConnected version 7 or above.
+ // If set to true, then weights-only op will use asymmetric quantization for
+ // inputs.
+ asymmetric_quantize_inputs: bool;
+}
+
+table SoftmaxOptions {
+ beta: float;
+}
+
+// An implementation of TensorFlow concat.
+table ConcatenationOptions {
+ axis:int;
+ fused_activation_function:ActivationFunctionType;
+}
+
+table AddOptions {
+ fused_activation_function:ActivationFunctionType;
+ // Parameters supported by version 3.
+ pot_scale_int16:bool = true;
+}
+
+table MulOptions {
+ fused_activation_function:ActivationFunctionType;
+}
+
+table L2NormOptions {
+ // This field is currently ignored in the L2 Norm Op.
+ fused_activation_function:ActivationFunctionType;
+}
+
+table LocalResponseNormalizationOptions {
+ radius:int;
+ bias:float;
+ alpha:float;
+ beta:float;
+}
+
+enum LSTMKernelType : byte {
+ // Full LSTM kernel which supports peephole and projection.
+ FULL = 0,
+ // Basic LSTM kernels. Equivalent to TensorFlow BasicLSTMCell.
+ BASIC = 1,
+}
+
+// An implementation of TensorFlow LSTMCell and CoupledInputForgetGateLSTMCell
+table LSTMOptions {
+ // Parameters for LSTM version 1 or above.
+ fused_activation_function:ActivationFunctionType;
+ cell_clip: float; // Optional, 0.0 means no clipping
+ proj_clip: float; // Optional, 0.0 means no clipping
+
+ // Parameters for LSTM version 2 or above.
+ // Basic kernel is only supported in version 2 or above.
+ kernel_type: LSTMKernelType = FULL;
+
+ // Parameters for LSTM version 4 or above.
+ asymmetric_quantize_inputs: bool;
+}
+
+// An implementation of TensorFlow dynamic_rnn with LSTMCell.
+table UnidirectionalSequenceLSTMOptions {
+ fused_activation_function:ActivationFunctionType;
+ cell_clip: float; // Optional, 0.0 means no clipping
+ proj_clip: float; // Optional, 0.0 means no clipping
+
+ // If true then first dimension is sequence, otherwise batch.
+ time_major:bool;
+
+ // Parameter for Unidirectional Sequence LSTM version 4.
+ asymmetric_quantize_inputs:bool;
+}
+
+table BidirectionalSequenceLSTMOptions {
+ // Parameters supported by version 1:
+ fused_activation_function:ActivationFunctionType;
+ cell_clip: float; // Optional, 0.0 means no clipping
+ proj_clip: float; // Optional, 0.0 means no clipping
+
+ // If true, store the outputs of both directions into the first output.
+ merge_outputs: bool;
+
+ // Parameters supported by version 2:
+ // If true then first dimension is sequence, otherwise batch.
+ // Version 1 implementations assumed time_major to be true, so this default
+ // value should never change.
+ time_major: bool = true;
+
+ // Parameters for version 3 or above.
+ asymmetric_quantize_inputs:bool;
+}
+
+table ResizeBilinearOptions {
+ new_height: int (deprecated);
+ new_width: int (deprecated);
+ align_corners: bool;
+ half_pixel_centers: bool;
+}
+
+table ResizeNearestNeighborOptions {
+ align_corners: bool;
+ half_pixel_centers: bool;
+}
+
+// A call operation options
+table CallOptions {
+ // The subgraph index that needs to be called.
+ subgraph:uint;
+}
+
+table PadOptions {
+}
+
+table PadV2Options {
+}
+
+table ReshapeOptions {
+ new_shape:[int];
+}
+
+table SpaceToBatchNDOptions {
+}
+
+table BatchToSpaceNDOptions {
+}
+
+table SkipGramOptions {
+ ngram_size: int;
+ max_skip_size: int;
+ include_all_ngrams: bool;
+}
+
+table SpaceToDepthOptions {
+ block_size: int;
+}
+
+table DepthToSpaceOptions {
+ block_size: int;
+}
+
+table SubOptions {
+ fused_activation_function:ActivationFunctionType;
+ // Parameters supported by version 5
+ pot_scale_int16:bool = true;
+}
+
+table DivOptions {
+ fused_activation_function:ActivationFunctionType;
+}
+
+table TopKV2Options {
+}
+
+enum CombinerType : byte {
+ SUM = 0,
+ MEAN = 1,
+ SQRTN = 2,
+}
+
+table EmbeddingLookupSparseOptions {
+ combiner:CombinerType;
+}
+
+table GatherOptions {
+ axis: int;
+ // Parameters for Gather version 5 or above.
+ batch_dims: int = 0;
+}
+
+table TransposeOptions {
+}
+
+table ExpOptions {
+}
+
+table CosOptions {
+}
+
+table ReducerOptions {
+ keep_dims: bool;
+}
+
+table SqueezeOptions {
+ squeeze_dims:[int];
+}
+
+table SplitOptions {
+ num_splits: int;
+}
+
+table SplitVOptions {
+ num_splits: int;
+}
+
+table StridedSliceOptions {
+ begin_mask: int;
+ end_mask: int;
+ ellipsis_mask: int;
+ new_axis_mask: int;
+ shrink_axis_mask: int;
+}
+
+table LogSoftmaxOptions {
+}
+
+table CastOptions {
+ in_data_type: TensorType;
+ out_data_type: TensorType;
+}
+
+table DequantizeOptions {
+}
+
+table MaximumMinimumOptions {
+}
+
+table TileOptions {
+}
+
+table ArgMaxOptions {
+ output_type : TensorType;
+}
+
+table ArgMinOptions {
+ output_type : TensorType;
+}
+
+table GreaterOptions {
+}
+
+table GreaterEqualOptions {
+}
+
+table LessOptions {
+}
+
+table LessEqualOptions {
+}
+
+table NegOptions {
+}
+
+table SelectOptions {
+}
+
+table SliceOptions {
+}
+
+table TransposeConvOptions {
+ padding:Padding;
+ stride_w:int;
+ stride_h:int;
+}
+
+table ExpandDimsOptions {
+}
+
+table SparseToDenseOptions {
+ validate_indices:bool;
+}
+
+table EqualOptions {
+}
+
+table NotEqualOptions {
+}
+
+table ShapeOptions {
+ // Optional output type of the operation (int32 or int64). Defaults to int32.
+ out_type : TensorType;
+}
+
+table RankOptions {
+}
+
+table PowOptions {
+}
+
+table FakeQuantOptions {
+ // Parameters supported by version 1:
+ min:float;
+ max:float;
+ num_bits:int;
+
+ // Parameters supported by version 2:
+ narrow_range:bool;
+}
+
+table PackOptions {
+ values_count:int;
+ axis:int;
+}
+
+table LogicalOrOptions {
+}
+
+table OneHotOptions {
+ axis:int;
+}
+
+table AbsOptions {
+}
+
+
+table HardSwishOptions {
+}
+
+table LogicalAndOptions {
+}
+
+table LogicalNotOptions {
+}
+
+table UnpackOptions {
+ num:int;
+ axis:int;
+}
+
+table FloorDivOptions {
+}
+
+table SquareOptions {
+}
+
+table ZerosLikeOptions {
+}
+
+table FillOptions {
+}
+
+table FloorModOptions {
+}
+
+table RangeOptions {
+}
+
+table LeakyReluOptions {
+ alpha:float;
+}
+
+table SquaredDifferenceOptions {
+}
+
+enum MirrorPadMode : byte {
+ // Doesn't include borders.
+ REFLECT = 0,
+ // Includes borders.
+ SYMMETRIC = 1,
+}
+
+table MirrorPadOptions {
+ mode:MirrorPadMode;
+}
+
+table UniqueOptions {
+ idx_out_type:TensorType = INT32;
+}
+
+table ReverseV2Options {
+}
+
+table AddNOptions {
+}
+
+table GatherNdOptions {
+}
+
+table WhereOptions {
+}
+
+table ReverseSequenceOptions {
+ seq_dim:int;
+ batch_dim:int = 0;
+}
+
+table MatrixDiagOptions {
+}
+
+table QuantizeOptions {
+}
+
+table MatrixSetDiagOptions {
+}
+
+table IfOptions {
+ then_subgraph_index:int;
+ else_subgraph_index:int;
+}
+
+table CallOnceOptions {
+ init_subgraph_index:int;
+}
+
+table WhileOptions {
+ cond_subgraph_index:int;
+ body_subgraph_index:int;
+}
+
+table NonMaxSuppressionV4Options {
+}
+
+table NonMaxSuppressionV5Options {
+}
+
+table ScatterNdOptions {
+}
+
+table SelectV2Options {
+}
+
+table DensifyOptions {
+}
+
+table SegmentSumOptions {
+}
+
+table BatchMatMulOptions {
+ adjoint_lhs:bool;
+ adjoint_rhs:bool;
+ // Parameters for BatchMatMul version 4 or above.
+ // If set to true, then weights-only op will use asymmetric quantization for
+ // inputs.
+ asymmetric_quantize_inputs: bool;
+}
+
+table CumsumOptions {
+ exclusive:bool;
+ reverse:bool;
+}
+
+table BroadcastToOptions {
+}
+
+table Rfft2dOptions {
+}
+
+table HashtableOptions {
+ // The identity of hash tables. This identity will be used across different
+ // subgraphs in the same interpreter instance.
+ table_id:int;
+ key_dtype:TensorType;
+ value_dtype:TensorType;
+}
+
+table HashtableFindOptions {
+}
+
+table HashtableImportOptions {
+}
+
+table HashtableSizeOptions {
+}
+
+table VarHandleOptions {
+ container:string;
+ shared_name:string;
+}
+
+table ReadVariableOptions {
+}
+
+table AssignVariableOptions {
+}
+
+table RandomOptions {
+ seed: long;
+ seed2: long;
+}
+
+table BucketizeOptions {
+ boundaries: [float]; // The bucket boundaries.
+}
+
+table GeluOptions {
+ approximate: bool;
+}
+
+table DynamicUpdateSliceOptions {
+}
+
+table UnsortedSegmentProdOptions {
+}
+
+table UnsortedSegmentMaxOptions {
+}
+
+table UnsortedSegmentSumOptions {
+}
+
+table ATan2Options {
+}
+
+table BCQGatherOptions {
+ input_hidden_size: int;
+ axis: int;
+}
+
+table BCQFullyConnectedOptions {
+ weights_hidden_size: int;
+ fused_activation_function:ActivationFunctionType;
+}
+
+table InstanceNormOptions {
+ epsilon:float;
+ fused_activation_function:ActivationFunctionType;
+}
+
+// An OperatorCode can be an enum value (BuiltinOperator) if the operator is a
+// builtin, or a string if the operator is custom.
+table OperatorCode {
+ // This field is for backward compatibility. This field will be used when
+ // the value of the extended builtin_code field has less than
+ // BulitinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES.
+ deprecated_builtin_code:byte;
+ custom_code:string;
+
+ // The version of the operator. The version need to be bumped whenever new
+ // parameters are introduced into an op.
+ version:int = 1;
+
+ // This field is introduced for resolving op builtin code shortage problem
+ // (the original BuiltinOperator enum field was represented as a byte).
+ // This field will be used when the value of the extended builtin_code field
+ // has greater than BulitinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES.
+ builtin_code:BuiltinOperator;
+}
+
+enum CustomOptionsFormat : byte {
+ FLEXBUFFERS = 0,
+}
+
+enum DataFormat : byte {
+ // For 2D data, NHWC(batch, height, width, channels)
+ // For 3D data, NDHWC(batch, depth, height, width, channels)
+ CHANNELS_LAST = 0,
+ // For 2D data, NCHW(batch, channels, height, width)
+ // For 3D data, NCDHW(batch, channels, depth, height, width)
+ CHANNELS_FIRST = 1,
+}
+
+// An operator takes tensors as inputs and outputs. The type of operation being
+// performed is determined by an index into the list of valid OperatorCodes,
+// while the specifics of each operations is configured using builtin_options
+// or custom_options.
+table Operator {
+ // Index into the operator_codes array. Using an integer here avoids
+ // complicate map lookups.
+ opcode_index:uint;
+
+ // Optional input are indicated by -1.
+ inputs:[int];
+ outputs:[int];
+
+ builtin_options:BuiltinOptions;
+ custom_options:[ubyte];
+ custom_options_format:CustomOptionsFormat;
+
+ // A list of booleans indicating the input tensors which are being mutated by
+ // this operator.(e.g. used by RNN and LSTM).
+ // For example, if the "inputs" array refers to 5 tensors and the second and
+ // fifth are mutable variables, then this list will contain
+ // [false, true, false, false, true].
+ //
+ // If the list is empty, no variable is mutated in this operator.
+ // The list either has the same length as `inputs`, or is empty.
+ mutating_variable_inputs:[bool];
+
+ // A list of indices to the subgraph's "tensors" that are internal to an Op.
+ // Internal tensors are those that do not flow in or out of the operation,
+ // but instead are part of internal computation. As such, the operation's
+ // implementation may manage its memory more efficiently. They are needed
+ // however (i.e. not just an implementation detail) since they are part of the
+ // computation, which may require relevant metadata such as quantization
+ // parameters.
+ intermediates:[int];
+}
+
+// The root type, defining a subgraph, which typically represents an entire
+// model.
+table SubGraph {
+ // A list of all tensors used in this subgraph.
+ tensors:[Tensor];
+
+ // Indices of the tensors that are inputs into this subgraph. Note this is
+ // the list of non-static tensors that feed into the subgraph for inference.
+ inputs:[int];
+
+ // Indices of the tensors that are outputs out of this subgraph. Note this is
+ // the list of output tensors that are considered the product of the
+ // subgraph's inference.
+ outputs:[int];
+
+ // All operators, in execution order.
+ operators:[Operator];
+
+ // Name of this subgraph (used for debugging).
+ name:string;
+
+ // Data format for input/output of SubGraph
+ data_format: DataFormat;
+}
+
+// Table of raw data buffers (used for constant tensors). Referenced by tensors
+// by index. The generous alignment accommodates mmap-friendly data structures.
+table Buffer {
+ data:[ubyte] (force_align: 16);
+}
+
+table Metadata {
+ // A human readable string to uniquely identify a Metadata.
+ name:string;
+ // An index to the buffers table.
+ buffer:uint;
+}
+
+// Map from an alias name of tensor to tensor index in the graph.
+// This is used in Signature def.
+table TensorMap {
+ // Represents the alias to use for this tensor.
+ name:string;
+
+ // The actual tensor index in the primary graph, that 'name' corresponds to.
+ tensor_index:uint;
+}
+
+// This corresponds to SignatureDef in Tensorflow SavedModel.
+// The SignatureDef will be part of the SavedModel provided for conversion.
+table SignatureDef {
+ // Named inputs for this signature.
+ inputs:[TensorMap];
+
+ // Named outputs for this signature.
+ outputs:[TensorMap];
+
+ // Key value which was in the Tensorflow SavedModel SignatureDef map.
+ signature_key:string;
+
+ // Model tag, deprecated.
+ deprecated_tag:string (deprecated);
+
+ // Index of subgraphs that corresponds to the exported method.
+ subgraph_index:uint;
+}
+
+table Model {
+ // Version of the schema.
+ version:uint;
+
+ // A list of all operator codes used in this model. This is
+ // kept in order because operators carry an index into this
+ // vector.
+ operator_codes:[OperatorCode];
+
+ // All the subgraphs of the model. The 0th is assumed to be the main
+ // model.
+ subgraphs:[SubGraph];
+
+ // A description of the model.
+ description:string;
+
+ // Buffers of the model.
+ // Note the 0th entry of this array must be an empty buffer (sentinel).
+ // This is a convention so that tensors without a buffer can provide 0 as
+ // their buffer.
+ buffers:[Buffer];
+
+ // Metadata about the model. Indirects into the existings buffers list.
+ // Deprecated, prefer to use metadata field.
+ metadata_buffer:[int];
+
+ // Metadata about the model.
+ metadata:[Metadata];
+
+ // Optional SignatureDefs for the model.
+ signature_defs:[SignatureDef];
+}
+
+root_type Model;
diff --git a/res/CircleSchema/0.6/circle_schema.fbs b/res/CircleSchema/0.6/circle_schema.fbs
new file mode 100644
index 000000000..cdc10361b
--- /dev/null
+++ b/res/CircleSchema/0.6/circle_schema.fbs
@@ -0,0 +1,1388 @@
+// Copyright (c) 2019~2023 Samsung Electronics Co., Ltd. All Rights Reserved
+// Copyright 2017 The TensorFlow Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Revision History
+//
+// Version Major.Minor
+//
+// Major version is schema version.
+// We keep schema version if it is compatible
+// Minor version is for human communication
+// It will not be stored in circle model.
+//
+// Version 0.0: Initial version. Based on TensorFlow Lite v1.13.1 schema.
+// Version 0.1: Based on TF v2.2-rc2 + more (from TensorFlow `56d281c`)
+// `BATCH_MATMUL` operator, `FLOAT64` tensor type,
+// `asymmetric_quantize_inputs` for several operator options
+// Version 0.2: BCQ_GATHER and BCQ_FULLY_CONNECTED are added.
+// Version 0.3: SHUFFLED16x1FLOAT32 is added.
+// Version 0.4: Base up to TensorFlow Lite v2.7.0 schema.
+// Version 0.5: Base up to TensorFlow Lite v2.10.1 schema.
+// Version 0.6: Base up to TensorFlow Lite v2.13.0 schema.
+
+namespace circle;
+
+// This corresponds to the version.
+file_identifier "CIR0";
+// File extension of any written files.
+file_extension "circle";
+
+// IMPORTANT: All new members of tables, enums and unions must be added at the
+// end to ensure backwards compatibility.
+
+// The type of data stored in a tensor.
+enum TensorType : byte {
+ FLOAT32 = 0,
+ FLOAT16 = 1,
+ INT32 = 2,
+ UINT8 = 3,
+ INT64 = 4,
+ STRING = 5,
+ BOOL = 6,
+ INT16 = 7,
+ COMPLEX64 = 8,
+ INT8 = 9,
+ FLOAT64 = 10,
+ COMPLEX128 = 11,
+ UINT64 = 12,
+ // Experimental: Resource and variant types are experimental, that are subject
+ // to change. Do not implement custom kernels using resource & variant types
+ // now.
+ RESOURCE = 13,
+ VARIANT = 14,
+ UINT32 = 15,
+ UINT16 = 16,
+ INT4 = 17,
+}
+
+// Custom quantization parameters for experimenting with new quantization
+// techniques.
+table CustomQuantization {
+ custom:[ubyte] (force_align: 16);
+}
+
+// Represents a specific quantization technique's parameters.
+union QuantizationDetails {
+ CustomQuantization,
+}
+
+// Parameters for converting a quantized tensor back to float.
+table QuantizationParameters {
+ // These four parameters are the asymmetric linear quantization parameters.
+ // Given a quantized value q, the corresponding float value f should be:
+ // f = scale * (q - zero_point)
+ // For other quantization types, the QuantizationDetails below is used.
+ min:[float]; // For importing back into tensorflow.
+ max:[float]; // For importing back into tensorflow.
+ scale:[float]; // For dequantizing the tensor's values.
+ zero_point:[long];
+
+ // If this is not none, the other quantization parameters (i.e. min, max,
+ // scale, zero_point fields above) are ignored and the value of the
+ // QuantizationDetails union should be used.
+ details:QuantizationDetails;
+
+ // Specifies the dimension of the Tensor's shape that the scales and
+ // zero_points correspond to. For example, a tensor t, with dims=[4, 3, 2, 1]
+ // with quantization params:
+ // scale=[1.0, 2.0, 3.0], zero_point=[1, 2, 3], quantization_dimension=1
+ // will be quantized across the second dimension of t.
+ // t[:, 0, :, :] will have scale[0]=1.0, zero_point[0]=1
+ // t[:, 1, :, :] will have scale[1]=2.0, zero_point[0]=2
+ // t[:, 2, :, :] will have scale[2]=3.0, zero_point[0]=3
+ quantized_dimension:int;
+}
+
+// Sparse tensors.
+// We use a modification of the TACO format.
+// Reference: http://tensor-compiler.org/kjolstad-oopsla17-tensor-compiler.pdf
+//
+// To encode a conceptual n-dimensional dense tensor with dims (d0, ..., dn-1),
+// potentially with a k-dimensional block (0 <= k <= n) with dims
+// (dn, ..., dn+k-1), the format needs to specify:
+// 1. In what order to traverse these dimensions. For example, to store a 2-D
+// matrix in row major order, the traversal order would be (d0, d1),
+// whereas to store it in column major order, the traversal order would be
+// (d1, d0). If the 2-D matrix has a 2-D inner block, the traversal order
+// could be (d0, d1, d2, d3).
+// 2. How each block dimension in (dn, ..., dn+k-1) maps to the original
+// tensor dimension in (d0, ..., dn-1).
+// 3. In the traversal order defined above, the format (dense vs. sparse) and
+// index metadata for each dimension. For a dense dimension, this is just
+// the size of that dimension. For a sparse dimension, it's the same as
+// the compressed index defined in the Compressed Sparse Row (CSR) format.
+// (http://scipy-lectures.org/advanced/scipy_sparse/csr_matrix.html)
+
+// The storage type for a dimension. Currently we support:
+// 1. DENSE: each coordinate in this dimension is stored implicitly.
+// 2. SPARSE_CSR: only the coordinates with non-zero elements are stored. The
+// compression technique is the same what CSR uses.
+// More types like a sparse dimension with a different compression technique
+// could be added to the list in the future.
+enum DimensionType : byte {
+ DENSE = 0,
+ SPARSE_CSR = 1,
+}
+
+table Int32Vector {
+ values:[int];
+}
+
+table Uint16Vector {
+ values:[ushort] (force_align: 4);
+}
+
+table Uint8Vector {
+ values:[ubyte] (force_align: 4);
+}
+
+// Variable-typed buffer to store the index metadata for a sparse dimension.
+// The widest type is Int32 instead of UInt32 because tensor's shape is a int32
+// vector. We don't want the per-dimensional index to overflow that range.
+union SparseIndexVector {
+ Int32Vector,
+ Uint16Vector,
+ Uint8Vector
+}
+
+table DimensionMetadata {
+ // Whether a dimension is dense or sparse.
+ format:DimensionType;
+ // Index metadata used for a dimension.
+ // - If format is DimensionType.DENSE then we use the dense_size field to
+ // store the size of that dimension. Each index in that dimension is
+ // stored implicitly.
+ // - If format is DimensionType.SPARSE_CSR then we use array_segments and
+ // array_indices to encode that dimension. array_segments represents how
+ // to segment the indices array, each segment corresponds to one element
+ // in the previous dimension. array_indices represents the index of the
+ // non-zero elements within this dimension (as those in the CSR matrix
+ // format, where the first array is row pointers and the second array is
+ // column indices).
+ dense_size:int;
+ array_segments:SparseIndexVector;
+ array_indices:SparseIndexVector;
+}
+
+// Parameters to encode a sparse TfLite tensor.
+table SparsityParameters {
+ // The traversal order of the dimensions defined in the `shape` field of the
+ // conceptual dense tensor. For a n-dimensional tensors with dims (d0, d1,
+ // ..., dn-1),
+ // - if not block sparse, the traversal_order is just a permutation of (d0,
+ // ..., dn-1). For example, a 2-D matrix stored in row-major order would
+ // have traversal_order = (d0, d1).
+ // - if block sparse with a k-dimensional block (0 <= k <= n), the
+ // traversal_order has n + k elements. The first n elements are still a
+ // permutation of (d0, ..., dn-1). The lask k elements are a permutation
+ // of (dn, ..., dn+k-1), defining how to traverse a block internally. For
+ // example, a 2-D matrix with 2-D blocks, both stored in row-major order
+ // would have traversal_order = (d0, d1, d2, d3).
+ traversal_order:[int];
+ // For an n-dimensional tensor with a k-dimensional block (0 <= k <= n),
+ // stores how a block dimension in (dn, ..., dn+k-1) maps to the original
+ // tensor dimension in (d0, ..., dn).
+ // It's stored in the order of (dn, ..., dn+k-1).
+ // If not block-sparse, this field is NULL.
+ block_map:[int];
+ // In the traversal order defined above, the metadata needed for
+ // each dimension to locate the non-zero values in the original dense tensor.
+ // The size of the dim_metadata array = the size of the traversal_order array
+ // = n + k.
+ dim_metadata:[DimensionMetadata];
+}
+
+// The nested tensor type for VARIANT type.
+table VariantSubType {
+ // The tensor shape.
+ shape:[int];
+ type:TensorType;
+ // If false, the rank or the number of tensor dimensions is unknown.
+ // If false, "shape" must be [].
+ has_rank: bool = false;
+}
+
+table Tensor {
+ // The tensor shape. The meaning of each entry is operator-specific but
+ // builtin ops use: [batch size, height, width, number of channels] (That's
+ // Tensorflow's NHWC).
+ shape:[int];
+ type:TensorType;
+ // An index that refers to the buffers table at the root of the model. Or,
+ // if there is no data buffer associated (i.e. intermediate results), then
+ // this is 0 (which refers to an always existent empty buffer).
+ //
+ // The data_buffer itself is an opaque container, with the assumption that the
+ // target device is little-endian. In addition, all builtin operators assume
+ // the memory is ordered such that if `shape` is [4, 3, 2], then index
+ // [i, j, k] maps to data_buffer[i*3*2 + j*2 + k].
+ buffer:uint;
+ name:string; // For debugging and importing back into tensorflow.
+ quantization:QuantizationParameters; // Optional.
+
+ is_variable:bool = false;
+
+ // Parameters to encode a sparse tensor. See the example in
+ // tensorflow/lite/testdata/sparse_tensor.json.
+ sparsity:SparsityParameters; // Optional.
+
+ // Encodes `shape` with unknown dimensions. Unknown dimensions are
+ // represented with -1.
+ shape_signature:[int]; // Optional.
+
+ // If false, the rank or the number of tensor dimensions is unknown.
+ // If false, "shape" must be [].
+ has_rank: bool = false;
+
+ // The nested Tensor types for VARIANT type. This is always empty for
+ // non-VARIANT types. This is optional because the nested type can be omitted.
+ // Currently only 1 subtype is supported. The field is defined as an array for
+ // flexibility of supporting multiple subtypes in the future.
+ variant_tensors:[VariantSubType];
+}
+
+// A list of builtin operators. Builtin operators are slightly faster than custom
+// ones, but not by much. Moreover, while custom operators accept an opaque
+// object containing configuration parameters, builtins have a predetermined
+// set of acceptable options.
+// LINT.IfChange
+enum BuiltinOperator : int32 {
+ BCQ_GATHER = -4,
+ BCQ_FULLY_CONNECTED = -3,
+ INSTANCE_NORM = -2,
+ ADD = 0,
+ AVERAGE_POOL_2D = 1,
+ CONCATENATION = 2,
+ CONV_2D = 3,
+ DEPTHWISE_CONV_2D = 4,
+ DEPTH_TO_SPACE = 5,
+ DEQUANTIZE = 6,
+ EMBEDDING_LOOKUP = 7,
+ FLOOR = 8,
+ FULLY_CONNECTED = 9,
+ HASHTABLE_LOOKUP = 10,
+ L2_NORMALIZATION = 11,
+ L2_POOL_2D = 12,
+ LOCAL_RESPONSE_NORMALIZATION = 13,
+ LOGISTIC = 14,
+ LSH_PROJECTION = 15,
+ LSTM = 16,
+ MAX_POOL_2D = 17,
+ MUL = 18,
+ RELU = 19,
+ // NOTE(aselle): RELU_N1_TO_1 used to be called RELU1, but it was renamed
+ // since different model developers use RELU1 in different ways. Never
+ // create another op called RELU1.
+ RELU_N1_TO_1 = 20,
+ RELU6 = 21,
+ RESHAPE = 22,
+ RESIZE_BILINEAR = 23,
+ RNN = 24,
+ SOFTMAX = 25,
+ SPACE_TO_DEPTH = 26,
+ SVDF = 27,
+ TANH = 28,
+ CONCAT_EMBEDDINGS = 29,
+ SKIP_GRAM = 30,
+ CALL = 31,
+ CUSTOM = 32,
+ EMBEDDING_LOOKUP_SPARSE = 33,
+ PAD = 34,
+ UNIDIRECTIONAL_SEQUENCE_RNN = 35,
+ GATHER = 36,
+ BATCH_TO_SPACE_ND = 37,
+ SPACE_TO_BATCH_ND = 38,
+ TRANSPOSE = 39,
+ MEAN = 40,
+ SUB = 41,
+ DIV = 42,
+ SQUEEZE = 43,
+ UNIDIRECTIONAL_SEQUENCE_LSTM = 44,
+ STRIDED_SLICE = 45,
+ BIDIRECTIONAL_SEQUENCE_RNN = 46,
+ EXP = 47,
+ TOPK_V2 = 48,
+ SPLIT = 49,
+ LOG_SOFTMAX = 50,
+ // DELEGATE is a special op type for the operations which are delegated to
+ // other backends.
+ // WARNING: Experimental interface, subject to change
+ DELEGATE = 51,
+ BIDIRECTIONAL_SEQUENCE_LSTM = 52,
+ CAST = 53,
+ PRELU = 54,
+ MAXIMUM = 55,
+ ARG_MAX = 56,
+ MINIMUM = 57,
+ LESS = 58,
+ NEG = 59,
+ PADV2 = 60,
+ GREATER = 61,
+ GREATER_EQUAL = 62,
+ LESS_EQUAL = 63,
+ SELECT = 64,
+ SLICE = 65,
+ SIN = 66,
+ TRANSPOSE_CONV = 67,
+ SPARSE_TO_DENSE = 68,
+ TILE = 69,
+ EXPAND_DIMS = 70,
+ EQUAL = 71,
+ NOT_EQUAL = 72,
+ LOG = 73,
+ SUM = 74,
+ SQRT = 75,
+ RSQRT = 76,
+ SHAPE = 77,
+ POW = 78,
+ ARG_MIN = 79,
+ FAKE_QUANT = 80,
+ REDUCE_PROD = 81,
+ REDUCE_MAX = 82,
+ PACK = 83,
+ LOGICAL_OR = 84,
+ ONE_HOT = 85,
+ LOGICAL_AND = 86,
+ LOGICAL_NOT = 87,
+ UNPACK = 88,
+ REDUCE_MIN = 89,
+ FLOOR_DIV = 90,
+ REDUCE_ANY = 91,
+ SQUARE = 92,
+ ZEROS_LIKE = 93,
+ FILL = 94,
+ FLOOR_MOD = 95,
+ RANGE = 96,
+ RESIZE_NEAREST_NEIGHBOR = 97,
+ LEAKY_RELU = 98,
+ SQUARED_DIFFERENCE = 99,
+ MIRROR_PAD = 100,
+ ABS = 101,
+ SPLIT_V = 102,
+ UNIQUE = 103,
+ CEIL = 104,
+ REVERSE_V2 = 105,
+ ADD_N = 106,
+ GATHER_ND = 107,
+ COS = 108,
+ WHERE = 109,
+ RANK = 110,
+ ELU = 111,
+ REVERSE_SEQUENCE = 112,
+ MATRIX_DIAG = 113,
+ QUANTIZE = 114,
+ MATRIX_SET_DIAG = 115,
+ ROUND = 116,
+ HARD_SWISH = 117,
+ IF = 118,
+ WHILE = 119,
+ NON_MAX_SUPPRESSION_V4 = 120,
+ NON_MAX_SUPPRESSION_V5 = 121,
+ SCATTER_ND = 122,
+ SELECT_V2 = 123,
+ DENSIFY = 124,
+ SEGMENT_SUM = 125,
+ BATCH_MATMUL = 126,
+ PLACEHOLDER_FOR_GREATER_OP_CODES = 127,
+ CUMSUM = 128,
+ CALL_ONCE = 129,
+ BROADCAST_TO = 130,
+ RFFT2D = 131,
+ CONV_3D = 132,
+ IMAG=133,
+ REAL=134,
+ COMPLEX_ABS=135,
+ HASHTABLE = 136,
+ HASHTABLE_FIND = 137,
+ HASHTABLE_IMPORT = 138,
+ HASHTABLE_SIZE = 139,
+ REDUCE_ALL = 140,
+ CONV_3D_TRANSPOSE = 141,
+ VAR_HANDLE = 142,
+ READ_VARIABLE = 143,
+ ASSIGN_VARIABLE = 144,
+ BROADCAST_ARGS = 145,
+ RANDOM_STANDARD_NORMAL = 146,
+ BUCKETIZE = 147,
+ RANDOM_UNIFORM = 148,
+ MULTINOMIAL = 149,
+ GELU = 150,
+ DYNAMIC_UPDATE_SLICE = 151,
+ RELU_0_TO_1 = 152,
+ UNSORTED_SEGMENT_PROD = 153,
+ UNSORTED_SEGMENT_MAX = 154,
+ UNSORTED_SEGMENT_SUM = 155,
+ ATAN2 = 156,
+ UNSORTED_SEGMENT_MIN = 157,
+ SIGN = 158,
+ BITCAST = 159,
+ BITWISE_XOR = 160,
+ RIGHT_SHIFT = 161,
+}
+// LINT.ThenChange(nnapi_linter/linter.proto)
+
+// Options for the builtin operators.
+union BuiltinOptions {
+ Conv2DOptions,
+ DepthwiseConv2DOptions,
+ ConcatEmbeddingsOptions,
+ LSHProjectionOptions,
+ Pool2DOptions,
+ SVDFOptions,
+ RNNOptions,
+ FullyConnectedOptions,
+ SoftmaxOptions,
+ ConcatenationOptions,
+ AddOptions,
+ L2NormOptions,
+ LocalResponseNormalizationOptions,
+ LSTMOptions,
+ ResizeBilinearOptions,
+ CallOptions,
+ ReshapeOptions,
+ SkipGramOptions,
+ SpaceToDepthOptions,
+ EmbeddingLookupSparseOptions,
+ MulOptions,
+ PadOptions,
+ GatherOptions,
+ BatchToSpaceNDOptions,
+ SpaceToBatchNDOptions,
+ TransposeOptions,
+ ReducerOptions,
+ SubOptions,
+ DivOptions,
+ SqueezeOptions,
+ SequenceRNNOptions,
+ StridedSliceOptions,
+ ExpOptions,
+ TopKV2Options,
+ SplitOptions,
+ LogSoftmaxOptions,
+ CastOptions,
+ DequantizeOptions,
+ MaximumMinimumOptions,
+ ArgMaxOptions,
+ LessOptions,
+ NegOptions,
+ PadV2Options,
+ GreaterOptions,
+ GreaterEqualOptions,
+ LessEqualOptions,
+ SelectOptions,
+ SliceOptions,
+ TransposeConvOptions,
+ SparseToDenseOptions,
+ TileOptions,
+ ExpandDimsOptions,
+ EqualOptions,
+ NotEqualOptions,
+ ShapeOptions,
+ PowOptions,
+ ArgMinOptions,
+ FakeQuantOptions,
+ PackOptions,
+ LogicalOrOptions,
+ OneHotOptions,
+ LogicalAndOptions,
+ LogicalNotOptions,
+ UnpackOptions,
+ FloorDivOptions,
+ SquareOptions,
+ ZerosLikeOptions,
+ FillOptions,
+ BidirectionalSequenceLSTMOptions,
+ BidirectionalSequenceRNNOptions,
+ UnidirectionalSequenceLSTMOptions,
+ FloorModOptions,
+ RangeOptions,
+ ResizeNearestNeighborOptions,
+ LeakyReluOptions,
+ SquaredDifferenceOptions,
+ MirrorPadOptions,
+ AbsOptions,
+ SplitVOptions,
+ UniqueOptions,
+ ReverseV2Options,
+ AddNOptions,
+ GatherNdOptions,
+ CosOptions,
+ WhereOptions,
+ RankOptions,
+ ReverseSequenceOptions,
+ MatrixDiagOptions,
+ QuantizeOptions,
+ MatrixSetDiagOptions,
+ HardSwishOptions,
+ IfOptions,
+ WhileOptions,
+ DepthToSpaceOptions,
+ NonMaxSuppressionV4Options,
+ NonMaxSuppressionV5Options,
+ ScatterNdOptions,
+ SelectV2Options,
+ DensifyOptions,
+ SegmentSumOptions,
+ BatchMatMulOptions,
+ CumsumOptions,
+ CallOnceOptions,
+ BroadcastToOptions,
+ Rfft2dOptions,
+ Conv3DOptions,
+ HashtableOptions,
+ HashtableFindOptions,
+ HashtableImportOptions,
+ HashtableSizeOptions,
+ VarHandleOptions,
+ ReadVariableOptions,
+ AssignVariableOptions,
+ RandomOptions,
+ BucketizeOptions,
+ GeluOptions,
+ DynamicUpdateSliceOptions,
+ UnsortedSegmentProdOptions,
+ UnsortedSegmentMaxOptions,
+ UnsortedSegmentMinOptions,
+ UnsortedSegmentSumOptions,
+ ATan2Options,
+ SignOptions,
+ BitcastOptions,
+ BitwiseXorOptions,
+ RightShiftOptions,
+ BCQGatherOptions = 252,
+ BCQFullyConnectedOptions = 253,
+ InstanceNormOptions = 254,
+}
+
+enum Padding : byte { SAME, VALID }
+
+enum ActivationFunctionType : byte {
+ NONE = 0,
+ RELU = 1,
+ RELU_N1_TO_1 = 2,
+ RELU6 = 3,
+ TANH = 4,
+ SIGN_BIT = 5,
+}
+
+table Conv2DOptions {
+ padding:Padding;
+ stride_w:int;
+ stride_h:int;
+ fused_activation_function:ActivationFunctionType;
+ dilation_w_factor:int = 1;
+ dilation_h_factor:int = 1;
+}
+
+// Options for both Conv3D and Conv3DTranspose.
+table Conv3DOptions {
+ padding:Padding;
+ stride_d:int;
+ stride_w:int;
+ stride_h:int;
+ fused_activation_function:ActivationFunctionType;
+ dilation_d_factor:int = 1;
+ dilation_w_factor:int = 1;
+ dilation_h_factor:int = 1;
+}
+
+table Pool2DOptions {
+ padding:Padding;
+ stride_w:int;
+ stride_h:int;
+ filter_width:int;
+ filter_height:int;
+ fused_activation_function:ActivationFunctionType;
+}
+
+table DepthwiseConv2DOptions {
+ // Parameters for DepthwiseConv version 1 or above.
+ padding:Padding;
+ stride_w:int;
+ stride_h:int;
+ // `depth_multiplier` is redundant. It's used by CPU kernels in
+ // TensorFlow 2.0 or below, but ignored in versions above.
+ // See comments in lite/c/builtin_op_data.h for more details.
+ depth_multiplier:int;
+ fused_activation_function:ActivationFunctionType;
+ // Parameters for DepthwiseConv version 2 or above.
+ dilation_w_factor:int = 1;
+ dilation_h_factor:int = 1;
+}
+
+table ConcatEmbeddingsOptions {
+ num_channels:int;
+ num_columns_per_channel:[int];
+ embedding_dim_per_channel:[int]; // This could be inferred from parameters.
+}
+
+enum LSHProjectionType: byte {
+ UNKNOWN = 0,
+ SPARSE = 1,
+ DENSE = 2,
+}
+
+table LSHProjectionOptions {
+ type: LSHProjectionType;
+}
+
+table SVDFOptions {
+ rank:int;
+ fused_activation_function:ActivationFunctionType;
+ // For weights-only quantization, use asymmetric quantization for non
+ // constant inputs at evaluation time.
+ asymmetric_quantize_inputs:bool;
+}
+
+// An implementation of TensorFlow RNNCell.
+table RNNOptions {
+ fused_activation_function:ActivationFunctionType;
+ asymmetric_quantize_inputs:bool;
+}
+
+// An implementation of TensorFlow dynamic_rnn with RNNCell.
+table SequenceRNNOptions {
+ time_major:bool;
+ fused_activation_function:ActivationFunctionType;
+ asymmetric_quantize_inputs:bool;
+}
+
+// An implementation of TensorFlow bidrectional_dynamic_rnn with RNNCell.
+table BidirectionalSequenceRNNOptions {
+ time_major:bool;
+ fused_activation_function:ActivationFunctionType;
+ merge_outputs: bool;
+ asymmetric_quantize_inputs:bool;
+}
+
+enum FullyConnectedOptionsWeightsFormat: byte {
+ DEFAULT = 0,
+ SHUFFLED4x16INT8 = 1,
+ SHUFFLED16x1FLOAT32 = 127
+}
+
+// An implementation of TensorFlow fully_connected (a.k.a Dense) layer.
+table FullyConnectedOptions {
+ // Parameters for FullyConnected version 1 or above.
+ fused_activation_function:ActivationFunctionType;
+
+ // Parameters for FullyConnected version 2 or above.
+ weights_format:FullyConnectedOptionsWeightsFormat = DEFAULT;
+
+ // Parameters for FullyConnected version 5 or above.
+ // If set to true, then the number of dimension is preserved. Furthermore,
+ // all but the last dimension of the input and output shapes will be equal.
+ keep_num_dims: bool;
+
+ // Parameters for FullyConnected version 7 or above.
+ // If set to true, then weights-only op will use asymmetric quantization for
+ // inputs.
+ asymmetric_quantize_inputs: bool;
+}
+
+table SoftmaxOptions {
+ beta: float;
+}
+
+// An implementation of TensorFlow concat.
+table ConcatenationOptions {
+ axis:int;
+ fused_activation_function:ActivationFunctionType;
+}
+
+table AddOptions {
+ fused_activation_function:ActivationFunctionType;
+ // Parameters supported by version 3.
+ pot_scale_int16:bool = true;
+}
+
+table MulOptions {
+ fused_activation_function:ActivationFunctionType;
+}
+
+table L2NormOptions {
+ // This field is currently ignored in the L2 Norm Op.
+ fused_activation_function:ActivationFunctionType;
+}
+
+table LocalResponseNormalizationOptions {
+ radius:int;
+ bias:float;
+ alpha:float;
+ beta:float;
+}
+
+enum LSTMKernelType : byte {
+ // Full LSTM kernel which supports peephole and projection.
+ FULL = 0,
+ // Basic LSTM kernels. Equivalent to TensorFlow BasicLSTMCell.
+ BASIC = 1,
+}
+
+// An implementation of TensorFlow LSTMCell and CoupledInputForgetGateLSTMCell
+table LSTMOptions {
+ // Parameters for LSTM version 1 or above.
+ fused_activation_function:ActivationFunctionType;
+ cell_clip: float; // Optional, 0.0 means no clipping
+ proj_clip: float; // Optional, 0.0 means no clipping
+
+ // Parameters for LSTM version 2 or above.
+ // Basic kernel is only supported in version 2 or above.
+ kernel_type: LSTMKernelType = FULL;
+
+ // Parameters for LSTM version 4 or above.
+ asymmetric_quantize_inputs: bool;
+}
+
+// An implementation of TensorFlow dynamic_rnn with LSTMCell.
+table UnidirectionalSequenceLSTMOptions {
+ fused_activation_function:ActivationFunctionType;
+ cell_clip: float; // Optional, 0.0 means no clipping
+ proj_clip: float; // Optional, 0.0 means no clipping
+
+ // If true then first dimension is sequence, otherwise batch.
+ time_major:bool;
+
+ // Parameter for Unidirectional Sequence LSTM version 3.
+ asymmetric_quantize_inputs:bool;
+
+ // Parameter for unidirectional sequence RNN version 4.
+ diagonal_recurrent_tensors:bool;
+}
+
+table BidirectionalSequenceLSTMOptions {
+ // Parameters supported by version 1:
+ fused_activation_function:ActivationFunctionType;
+ cell_clip: float; // Optional, 0.0 means no clipping
+ proj_clip: float; // Optional, 0.0 means no clipping
+
+ // If true, store the outputs of both directions into the first output.
+ merge_outputs: bool;
+
+ // Parameters supported by version 2:
+ // If true then first dimension is sequence, otherwise batch.
+ // Version 1 implementations assumed time_major to be true, so this default
+ // value should never change.
+ time_major: bool = true;
+
+ // Parameters for version 3 or above.
+ asymmetric_quantize_inputs:bool;
+}
+
+table ResizeBilinearOptions {
+ new_height: int (deprecated);
+ new_width: int (deprecated);
+ align_corners: bool;
+ half_pixel_centers: bool;
+}
+
+table ResizeNearestNeighborOptions {
+ align_corners: bool;
+ half_pixel_centers: bool;
+}
+
+// A call operation options
+table CallOptions {
+ // The subgraph index that needs to be called.
+ subgraph:uint;
+}
+
+table PadOptions {
+}
+
+table PadV2Options {
+}
+
+table ReshapeOptions {
+ new_shape:[int];
+}
+
+table SpaceToBatchNDOptions {
+}
+
+table BatchToSpaceNDOptions {
+}
+
+table SkipGramOptions {
+ ngram_size: int;
+ max_skip_size: int;
+ include_all_ngrams: bool;
+}
+
+table SpaceToDepthOptions {
+ block_size: int;
+}
+
+table DepthToSpaceOptions {
+ block_size: int;
+}
+
+table SubOptions {
+ fused_activation_function:ActivationFunctionType;
+ // Parameters supported by version 5
+ pot_scale_int16:bool = true;
+}
+
+table DivOptions {
+ fused_activation_function:ActivationFunctionType;
+}
+
+table TopKV2Options {
+}
+
+enum CombinerType : byte {
+ SUM = 0,
+ MEAN = 1,
+ SQRTN = 2,
+}
+
+table EmbeddingLookupSparseOptions {
+ combiner:CombinerType;
+}
+
+table GatherOptions {
+ axis: int;
+ // Parameters for Gather version 5 or above.
+ batch_dims: int = 0;
+}
+
+table TransposeOptions {
+}
+
+table ExpOptions {
+}
+
+table CosOptions {
+}
+
+table ReducerOptions {
+ keep_dims: bool;
+}
+
+table SqueezeOptions {
+ squeeze_dims:[int];
+}
+
+table SplitOptions {
+ num_splits: int;
+}
+
+table SplitVOptions {
+ num_splits: int;
+}
+
+table StridedSliceOptions {
+ begin_mask: int;
+ end_mask: int;
+ ellipsis_mask: int;
+ new_axis_mask: int;
+ shrink_axis_mask: int;
+}
+
+table LogSoftmaxOptions {
+}
+
+table CastOptions {
+ in_data_type: TensorType;
+ out_data_type: TensorType;
+}
+
+table DequantizeOptions {
+}
+
+table MaximumMinimumOptions {
+}
+
+table TileOptions {
+}
+
+table ArgMaxOptions {
+ output_type : TensorType;
+}
+
+table ArgMinOptions {
+ output_type : TensorType;
+}
+
+table GreaterOptions {
+}
+
+table GreaterEqualOptions {
+}
+
+table LessOptions {
+}
+
+table LessEqualOptions {
+}
+
+table NegOptions {
+}
+
+table SelectOptions {
+}
+
+table SliceOptions {
+}
+
+table TransposeConvOptions {
+ // Parameters supported by version 1, 2, 3:
+ padding:Padding;
+ stride_w:int;
+ stride_h:int;
+
+ // Parameters supported by version 4:
+ fused_activation_function:ActivationFunctionType = NONE;
+}
+
+table ExpandDimsOptions {
+}
+
+table SparseToDenseOptions {
+ validate_indices:bool;
+}
+
+table EqualOptions {
+}
+
+table NotEqualOptions {
+}
+
+table ShapeOptions {
+ // Optional output type of the operation (int32 or int64). Defaults to int32.
+ out_type : TensorType;
+}
+
+table RankOptions {
+}
+
+table PowOptions {
+}
+
+table FakeQuantOptions {
+ // Parameters supported by version 1:
+ min:float;
+ max:float;
+ num_bits:int;
+
+ // Parameters supported by version 2:
+ narrow_range:bool;
+}
+
+table PackOptions {
+ values_count:int;
+ axis:int;
+}
+
+table LogicalOrOptions {
+}
+
+table OneHotOptions {
+ axis:int;
+}
+
+table AbsOptions {
+}
+
+
+table HardSwishOptions {
+}
+
+table LogicalAndOptions {
+}
+
+table LogicalNotOptions {
+}
+
+table UnpackOptions {
+ num:int;
+ axis:int;
+}
+
+table FloorDivOptions {
+}
+
+table SquareOptions {
+}
+
+table ZerosLikeOptions {
+}
+
+table FillOptions {
+}
+
+table FloorModOptions {
+}
+
+table RangeOptions {
+}
+
+table LeakyReluOptions {
+ alpha:float;
+}
+
+table SquaredDifferenceOptions {
+}
+
+enum MirrorPadMode : byte {
+ // Doesn't include borders.
+ REFLECT = 0,
+ // Includes borders.
+ SYMMETRIC = 1,
+}
+
+table MirrorPadOptions {
+ mode:MirrorPadMode;
+}
+
+table UniqueOptions {
+ idx_out_type:TensorType = INT32;
+}
+
+table ReverseV2Options {
+}
+
+table AddNOptions {
+}
+
+table GatherNdOptions {
+}
+
+table WhereOptions {
+}
+
+table ReverseSequenceOptions {
+ seq_dim:int;
+ batch_dim:int = 0;
+}
+
+table MatrixDiagOptions {
+}
+
+table QuantizeOptions {
+}
+
+table MatrixSetDiagOptions {
+}
+
+table IfOptions {
+ then_subgraph_index:int;
+ else_subgraph_index:int;
+}
+
+table CallOnceOptions {
+ init_subgraph_index:int;
+}
+
+table WhileOptions {
+ cond_subgraph_index:int;
+ body_subgraph_index:int;
+}
+
+table NonMaxSuppressionV4Options {
+}
+
+table NonMaxSuppressionV5Options {
+}
+
+table ScatterNdOptions {
+}
+
+table SelectV2Options {
+}
+
+table DensifyOptions {
+}
+
+table SegmentSumOptions {
+}
+
+table BatchMatMulOptions {
+ adjoint_lhs:bool;
+ adjoint_rhs:bool;
+ // Parameters for BatchMatMul version 4 or above.
+ // If set to true, then weights-only op will use asymmetric quantization for
+ // inputs.
+ asymmetric_quantize_inputs: bool;
+}
+
+table CumsumOptions {
+ exclusive:bool;
+ reverse:bool;
+}
+
+table BroadcastToOptions {
+}
+
+table Rfft2dOptions {
+}
+
+table HashtableOptions {
+ // The identity of hash tables. This identity will be used across different
+ // subgraphs in the same interpreter instance.
+ table_id:int;
+ key_dtype:TensorType;
+ value_dtype:TensorType;
+}
+
+table HashtableFindOptions {
+}
+
+table HashtableImportOptions {
+}
+
+table HashtableSizeOptions {
+}
+
+table VarHandleOptions {
+ container:string;
+ shared_name:string;
+}
+
+table ReadVariableOptions {
+}
+
+table AssignVariableOptions {
+}
+
+table RandomOptions {
+ seed: long;
+ seed2: long;
+}
+
+table BucketizeOptions {
+ boundaries: [float]; // The bucket boundaries.
+}
+
+table GeluOptions {
+ approximate: bool;
+}
+
+table DynamicUpdateSliceOptions {
+}
+
+table UnsortedSegmentProdOptions {
+}
+
+table UnsortedSegmentMaxOptions {
+}
+
+table UnsortedSegmentSumOptions {
+}
+
+table ATan2Options {
+}
+
+table UnsortedSegmentMinOptions{
+}
+
+table SignOptions {
+}
+
+table BitcastOptions {
+}
+
+table BitwiseXorOptions {
+}
+
+table RightShiftOptions {
+}
+
+table BCQGatherOptions {
+ input_hidden_size: int;
+ axis: int;
+}
+
+table BCQFullyConnectedOptions {
+ weights_hidden_size: int;
+ fused_activation_function:ActivationFunctionType;
+}
+
+table InstanceNormOptions {
+ epsilon:float;
+ fused_activation_function:ActivationFunctionType;
+}
+
+// An OperatorCode can be an enum value (BuiltinOperator) if the operator is a
+// builtin, or a string if the operator is custom.
+table OperatorCode {
+ // This field is for backward compatibility. This field will be used when
+ // the value of the extended builtin_code field has less than
+ // BulitinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES.
+ deprecated_builtin_code:byte;
+ custom_code:string;
+
+ // The version of the operator. The version need to be bumped whenever new
+ // parameters are introduced into an op.
+ version:int = 1;
+
+ // This field is introduced for resolving op builtin code shortage problem
+ // (the original BuiltinOperator enum field was represented as a byte).
+ // This field will be used when the value of the extended builtin_code field
+ // has greater than BulitinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES.
+ builtin_code:BuiltinOperator;
+}
+
+enum CustomOptionsFormat : byte {
+ FLEXBUFFERS = 0,
+}
+
+enum DataFormat : byte {
+ // For 2D data, NHWC(batch, height, width, channels)
+ // For 3D data, NDHWC(batch, depth, height, width, channels)
+ CHANNELS_LAST = 0,
+ // For 2D data, NCHW(batch, channels, height, width)
+ // For 3D data, NCDHW(batch, channels, depth, height, width)
+ CHANNELS_FIRST = 1,
+}
+
+// An operator takes tensors as inputs and outputs. The type of operation being
+// performed is determined by an index into the list of valid OperatorCodes,
+// while the specifics of each operations is configured using builtin_options
+// or custom_options.
+table Operator {
+ // Index into the operator_codes array. Using an integer here avoids
+ // complicate map lookups.
+ opcode_index:uint;
+
+ // Optional input are indicated by -1.
+ inputs:[int];
+ outputs:[int];
+
+ builtin_options:BuiltinOptions;
+ custom_options:[ubyte];
+ custom_options_format:CustomOptionsFormat;
+
+ // A list of booleans indicating the input tensors which are being mutated by
+ // this operator.(e.g. used by RNN and LSTM).
+ // For example, if the "inputs" array refers to 5 tensors and the second and
+ // fifth are mutable variables, then this list will contain
+ // [false, true, false, false, true].
+ //
+ // If the list is empty, no variable is mutated in this operator.
+ // The list either has the same length as `inputs`, or is empty.
+ mutating_variable_inputs:[bool];
+
+ // A list of indices to the subgraph's "tensors" that are internal to an Op.
+ // Internal tensors are those that do not flow in or out of the operation,
+ // but instead are part of internal computation. As such, the operation's
+ // implementation may manage its memory more efficiently. They are needed
+ // however (i.e. not just an implementation detail) since they are part of the
+ // computation, which may require relevant metadata such as quantization
+ // parameters.
+ intermediates:[int];
+}
+
+// The root type, defining a subgraph, which typically represents an entire
+// model.
+table SubGraph {
+ // A list of all tensors used in this subgraph.
+ tensors:[Tensor];
+
+ // Indices of the tensors that are inputs into this subgraph. Note this is
+ // the list of non-static tensors that feed into the subgraph for inference.
+ inputs:[int];
+
+ // Indices of the tensors that are outputs out of this subgraph. Note this is
+ // the list of output tensors that are considered the product of the
+ // subgraph's inference.
+ outputs:[int];
+
+ // All operators, in execution order.
+ operators:[Operator];
+
+ // Name of this subgraph (used for debugging).
+ name:string;
+
+ // Data format for input/output of SubGraph
+ data_format: DataFormat;
+}
+
+// Table of raw data buffers (used for constant tensors). Referenced by tensors
+// by index. The generous alignment accommodates mmap-friendly data structures.
+table Buffer {
+ data:[ubyte] (force_align: 16);
+}
+
+table Metadata {
+ // A human readable string to uniquely identify a Metadata.
+ name:string;
+ // An index to the buffers table.
+ buffer:uint;
+}
+
+// Map from an alias name of tensor to tensor index in the graph.
+// This is used in Signature def.
+table TensorMap {
+ // Represents the alias to use for this tensor.
+ name:string;
+
+ // The actual tensor index in the primary graph, that 'name' corresponds to.
+ tensor_index:uint;
+}
+
+// This corresponds to SignatureDef in Tensorflow SavedModel.
+// The SignatureDef will be part of the SavedModel provided for conversion.
+table SignatureDef {
+ // Named inputs for this signature.
+ inputs:[TensorMap];
+
+ // Named outputs for this signature.
+ outputs:[TensorMap];
+
+ // Key value which was in the Tensorflow SavedModel SignatureDef map.
+ signature_key:string;
+
+ // Model tag, deprecated.
+ deprecated_tag:string (deprecated);
+
+ // Index of subgraphs that corresponds to the exported method.
+ subgraph_index:uint;
+}
+
+table Model {
+ // Version of the schema.
+ version:uint;
+
+ // A list of all operator codes used in this model. This is
+ // kept in order because operators carry an index into this
+ // vector.
+ operator_codes:[OperatorCode];
+
+ // All the subgraphs of the model. The 0th is assumed to be the main
+ // model.
+ subgraphs:[SubGraph];
+
+ // A description of the model.
+ description:string;
+
+ // Buffers of the model.
+ // Note the 0th entry of this array must be an empty buffer (sentinel).
+ // This is a convention so that tensors without a buffer can provide 0 as
+ // their buffer.
+ buffers:[Buffer];
+
+ // Metadata about the model. Indirects into the existings buffers list.
+ // Deprecated, prefer to use metadata field.
+ metadata_buffer:[int];
+
+ // Metadata about the model.
+ metadata:[Metadata];
+
+ // Optional SignatureDefs for the model.
+ signature_defs:[SignatureDef];
+}
+
+root_type Model;
diff --git a/res/PyTorchExamples/ptem.py b/res/PyTorchExamples/ptem.py
index 95d1928a1..6cc28b66a 100755
--- a/res/PyTorchExamples/ptem.py
+++ b/res/PyTorchExamples/ptem.py
@@ -55,11 +55,7 @@ for example in args.examples:
onnx_model_path = output_folder + example + ".onnx"
torch.onnx.export(
- module._model_,
- module._dummy_,
- onnx_model_path,
- verbose=True,
- opset_version=opset_version)
+ module._model_, module._dummy_, onnx_model_path, opset_version=opset_version)
print("Generate '" + example + ".onnx' - Done")
onnx_model = onnx.load(onnx_model_path)
diff --git a/res/TensorFlowLiteRecipes/Gelu_000/test.recipe b/res/TensorFlowLiteRecipes/Gelu_000/test.recipe
new file mode 100644
index 000000000..1c4da104c
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Gelu_000/test.recipe
@@ -0,0 +1,20 @@
+operand {
+ name: "ifm"
+ type: FLOAT32
+ shape { dim: 1 dim: 3 dim: 3 dim: 2 }
+}
+operand {
+ name: "ofm"
+ type: FLOAT32
+ shape { dim: 1 dim: 3 dim: 3 dim: 2 }
+}
+operation {
+ type: "Gelu"
+ gelu_options {
+ approximate: false
+ }
+ input: "ifm"
+ output: "ofm"
+}
+input: "ifm"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/Gelu_000/test.reverse b/res/TensorFlowLiteRecipes/Gelu_000/test.reverse
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Gelu_000/test.reverse
diff --git a/res/TensorFlowLiteRecipes/HardSwish_000/test.recipe b/res/TensorFlowLiteRecipes/HardSwish_000/test.recipe
new file mode 100644
index 000000000..9dab36e20
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/HardSwish_000/test.recipe
@@ -0,0 +1,17 @@
+operand {
+ name: "ifm"
+ type: FLOAT32
+ shape { dim: 1 dim: 3 dim: 3 dim: 2 }
+}
+operand {
+ name: "ofm"
+ type: FLOAT32
+ shape { dim: 1 dim: 3 dim: 3 dim: 2 }
+}
+operation {
+ type: "HardSwish"
+ input: "ifm"
+ output: "ofm"
+}
+input: "ifm"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/HardSwish_000/test.reverse b/res/TensorFlowLiteRecipes/HardSwish_000/test.reverse
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/HardSwish_000/test.reverse
diff --git a/res/TensorFlowLiteRecipes/HardSwish_001/test.recipe b/res/TensorFlowLiteRecipes/HardSwish_001/test.recipe
new file mode 100644
index 000000000..a712e236c
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/HardSwish_001/test.recipe
@@ -0,0 +1,17 @@
+operand {
+ name: "ifm"
+ type: FLOAT32
+ shape { dim: 1 dim: 16 dim: 16 dim: 128 }
+}
+operand {
+ name: "ofm"
+ type: FLOAT32
+ shape { dim: 1 dim: 16 dim: 16 dim: 128 }
+}
+operation {
+ type: "HardSwish"
+ input: "ifm"
+ output: "ofm"
+}
+input: "ifm"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/HardSwish_001/test.rule b/res/TensorFlowLiteRecipes/HardSwish_001/test.rule
new file mode 100644
index 000000000..6970e2628
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/HardSwish_001/test.rule
@@ -0,0 +1,8 @@
+# To check if HardSwish is converted to Add, Mul and Relu6 operations
+
+RULE "VERIFY_FILE_FORMAT" $(verify_file_format) '=' 1
+
+RULE "ADD_EXIST" $(op_count ADD) '=' 1
+RULE "MUL_EXIST" $(op_count MUL) '=' 2
+RULE "RELU6_EXIST" $(op_count RELU6) '=' 1
+RULE "HARDSWISH_NOT_EXIST" $(op_count HARDSWISH) '=' 0
diff --git a/res/TensorFlowLiteRecipes/Net_Gelu_000/test.recipe b/res/TensorFlowLiteRecipes/Net_Gelu_000/test.recipe
new file mode 100644
index 000000000..ae7f823e8
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Net_Gelu_000/test.recipe
@@ -0,0 +1,100 @@
+operand {
+ name: "ifm"
+ type: FLOAT32
+ shape { dim: 1 dim: 5 dim: 5 dim: 3 }
+}
+operand {
+ name: "mul_sqrt"
+ type: FLOAT32
+ shape { dim: 1 dim: 5 dim: 5 dim: 3 }
+}
+operand {
+ name: "sqrt_2_inv"
+ type: FLOAT32
+ shape { dim: 1 }
+ filler {
+ tag: "explicit"
+ arg: "0.7071067690849304"
+ }
+}
+operand {
+ name: "erf"
+ type: FLOAT32
+ shape { dim: 1 dim: 5 dim: 5 dim: 3 }
+}
+operand {
+ name: "add_one"
+ type: FLOAT32
+ shape { dim: 1 dim: 5 dim: 5 dim: 3 }
+}
+operand {
+ name: "one"
+ type: FLOAT32
+ shape { dim: 1 }
+ filler {
+ tag: "explicit"
+ arg: "1.0"
+ }
+}
+operand {
+ name: "mul"
+ type: FLOAT32
+ shape { dim: 1 dim: 5 dim: 5 dim: 3 }
+}
+operand {
+ name: "mul_half"
+ type: FLOAT32
+ shape { dim: 1 dim: 5 dim: 5 dim: 3 }
+}
+operand {
+ name: "half"
+ type: FLOAT32
+ shape { dim: 1 }
+ filler {
+ tag: "explicit"
+ arg: "0.5"
+ }
+}
+operation {
+ type: "Mul"
+ input: "ifm"
+ input: "sqrt_2_inv"
+ output: "mul_sqrt"
+ mul_options {
+ activation: NONE
+ }
+}
+operation {
+ type: "Erf"
+ input: "mul_sqrt"
+ output: "erf"
+}
+operation {
+ type: "Add"
+ input: "erf"
+ input: "one"
+ output: "add_one"
+ add_options {
+ activation: NONE
+ }
+}
+operation {
+ type: "Mul"
+ input: "ifm"
+ input: "add_one"
+ output: "mul"
+ mul_options {
+ activation: NONE
+ }
+}
+operation {
+ type: "Mul"
+ input: "mul"
+ input: "half"
+ output: "mul_half"
+ mul_options {
+ activation: NONE
+ }
+}
+input: "ifm"
+output: "mul_half"
diff --git a/res/TensorFlowLiteRecipes/Net_Gelu_000/test.rule b/res/TensorFlowLiteRecipes/Net_Gelu_000/test.rule
new file mode 100644
index 000000000..de5a76972
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Net_Gelu_000/test.rule
@@ -0,0 +1,8 @@
+# To check if Fuse Gelu works
+
+RULE "VERIFY_FILE_FORMAT" $(verify_file_format) '=' 1
+
+RULE "GELU_EXIST" $(op_count GELU) '=' 1
+RULE "NO_MUL" $(op_count MUL) '=' 0
+RULE "NO_ADD" $(op_count ADD) '=' 0
+RULE "NO_CUSTOM" $(op_count 'CUSTOM(Erf)') '=' 0
diff --git a/res/TensorFlowLiteRecipes/Net_Gelu_001/test.recipe b/res/TensorFlowLiteRecipes/Net_Gelu_001/test.recipe
new file mode 100644
index 000000000..76337293a
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Net_Gelu_001/test.recipe
@@ -0,0 +1,100 @@
+operand {
+ name: "ifm"
+ type: FLOAT32
+ shape { dim: 1 dim: 5 dim: 5 dim: 3 }
+}
+operand {
+ name: "mul_sqrt"
+ type: FLOAT32
+ shape { dim: 1 dim: 5 dim: 5 dim: 3 }
+}
+operand {
+ name: "sqrt_2_inv"
+ type: FLOAT32
+ shape { dim: 1 }
+ filler {
+ tag: "explicit"
+ arg: "0.7071067690849304"
+ }
+}
+operand {
+ name: "erf"
+ type: FLOAT32
+ shape { dim: 1 dim: 5 dim: 5 dim: 3 }
+}
+operand {
+ name: "add_one"
+ type: FLOAT32
+ shape { dim: 1 dim: 5 dim: 5 dim: 3 }
+}
+operand {
+ name: "one"
+ type: FLOAT32
+ shape { dim: 1 }
+ filler {
+ tag: "explicit"
+ arg: "1.0"
+ }
+}
+operand {
+ name: "mul"
+ type: FLOAT32
+ shape { dim: 1 dim: 5 dim: 5 dim: 3 }
+}
+operand {
+ name: "mul_half"
+ type: FLOAT32
+ shape { dim: 1 dim: 5 dim: 5 dim: 3 }
+}
+operand {
+ name: "half"
+ type: FLOAT32
+ shape { dim: 1 }
+ filler {
+ tag: "explicit"
+ arg: "0.5"
+ }
+}
+operation {
+ type: "Mul"
+ input: "ifm"
+ input: "sqrt_2_inv"
+ output: "mul_sqrt"
+ mul_options {
+ activation: NONE
+ }
+}
+operation {
+ type: "Erf"
+ input: "mul_sqrt"
+ output: "erf"
+}
+operation {
+ type: "Add"
+ input: "erf"
+ input: "one"
+ output: "add_one"
+ add_options {
+ activation: NONE
+ }
+}
+operation {
+ type: "Mul"
+ input: "ifm"
+ input: "half"
+ output: "mul_half"
+ mul_options {
+ activation: NONE
+ }
+}
+operation {
+ type: "Mul"
+ input: "mul_half"
+ input: "add_one"
+ output: "mul"
+ mul_options {
+ activation: NONE
+ }
+}
+input: "ifm"
+output: "mul"
diff --git a/res/TensorFlowLiteRecipes/Net_Gelu_001/test.rule b/res/TensorFlowLiteRecipes/Net_Gelu_001/test.rule
new file mode 100644
index 000000000..de5a76972
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Net_Gelu_001/test.rule
@@ -0,0 +1,8 @@
+# To check if Fuse Gelu works
+
+RULE "VERIFY_FILE_FORMAT" $(verify_file_format) '=' 1
+
+RULE "GELU_EXIST" $(op_count GELU) '=' 1
+RULE "NO_MUL" $(op_count MUL) '=' 0
+RULE "NO_ADD" $(op_count ADD) '=' 0
+RULE "NO_CUSTOM" $(op_count 'CUSTOM(Erf)') '=' 0
diff --git a/res/TensorFlowLiteRecipes/Net_TConv_Add_000/test.recipe b/res/TensorFlowLiteRecipes/Net_TConv_Add_000/test.recipe
index afb9a9c4d..dd2ab9d80 100644
--- a/res/TensorFlowLiteRecipes/Net_TConv_Add_000/test.recipe
+++ b/res/TensorFlowLiteRecipes/Net_TConv_Add_000/test.recipe
@@ -78,6 +78,7 @@ operation {
padding: VALID
stride_w: 1
stride_h: 1
+ activation: NONE
}
}
operation {
diff --git a/res/TensorFlowLiteRecipes/Net_TConv_Add_001/test.recipe b/res/TensorFlowLiteRecipes/Net_TConv_Add_001/test.recipe
index b1c9784b0..67cce945f 100644
--- a/res/TensorFlowLiteRecipes/Net_TConv_Add_001/test.recipe
+++ b/res/TensorFlowLiteRecipes/Net_TConv_Add_001/test.recipe
@@ -84,6 +84,7 @@ operation {
padding: VALID
stride_w: 1
stride_h: 1
+ activation: NONE
}
}
operation {
diff --git a/res/TensorFlowLiteRecipes/Net_TConv_Add_002/test.recipe b/res/TensorFlowLiteRecipes/Net_TConv_Add_002/test.recipe
index 426551485..9021911be 100644
--- a/res/TensorFlowLiteRecipes/Net_TConv_Add_002/test.recipe
+++ b/res/TensorFlowLiteRecipes/Net_TConv_Add_002/test.recipe
@@ -78,6 +78,7 @@ operation {
padding: VALID
stride_w: 1
stride_h: 1
+ activation: NONE
}
}
operation {
diff --git a/res/TensorFlowLiteRecipes/Net_TConv_BN_000/test.recipe b/res/TensorFlowLiteRecipes/Net_TConv_BN_000/test.recipe
index ef329e1ac..065946d37 100644
--- a/res/TensorFlowLiteRecipes/Net_TConv_BN_000/test.recipe
+++ b/res/TensorFlowLiteRecipes/Net_TConv_BN_000/test.recipe
@@ -99,6 +99,7 @@ operation {
padding: VALID
stride_w: 1
stride_h: 1
+ activation: NONE
}
}
operation {
diff --git a/res/TensorFlowLiteRecipes/Net_TConv_BN_001/test.recipe b/res/TensorFlowLiteRecipes/Net_TConv_BN_001/test.recipe
index 1b329bafc..25557ab21 100644
--- a/res/TensorFlowLiteRecipes/Net_TConv_BN_001/test.recipe
+++ b/res/TensorFlowLiteRecipes/Net_TConv_BN_001/test.recipe
@@ -99,6 +99,7 @@ operation {
padding: VALID
stride_w: 1
stride_h: 1
+ activation: NONE
}
}
operation {
diff --git a/res/TensorFlowLiteRecipes/Net_TConv_BN_002/test.recipe b/res/TensorFlowLiteRecipes/Net_TConv_BN_002/test.recipe
index a8af8e497..48068e971 100644
--- a/res/TensorFlowLiteRecipes/Net_TConv_BN_002/test.recipe
+++ b/res/TensorFlowLiteRecipes/Net_TConv_BN_002/test.recipe
@@ -102,6 +102,7 @@ operation {
padding: VALID
stride_w: 1
stride_h: 1
+ activation: NONE
}
}
operation {
diff --git a/res/TensorFlowLiteRecipes/Net_TConv_BN_003/test.recipe b/res/TensorFlowLiteRecipes/Net_TConv_BN_003/test.recipe
index c28e50880..cb1959a58 100644
--- a/res/TensorFlowLiteRecipes/Net_TConv_BN_003/test.recipe
+++ b/res/TensorFlowLiteRecipes/Net_TConv_BN_003/test.recipe
@@ -111,6 +111,7 @@ operation {
padding: VALID
stride_w: 1
stride_h: 1
+ activation: NONE
}
}
operation {
diff --git a/res/TensorFlowLiteRecipes/Net_TConv_BN_004/test.recipe b/res/TensorFlowLiteRecipes/Net_TConv_BN_004/test.recipe
index b75527a98..5bc06dd1d 100644
--- a/res/TensorFlowLiteRecipes/Net_TConv_BN_004/test.recipe
+++ b/res/TensorFlowLiteRecipes/Net_TConv_BN_004/test.recipe
@@ -73,6 +73,7 @@ operation {
padding: VALID
stride_w: 1
stride_h: 1
+ activation: NONE
}
}
diff --git a/res/TensorFlowLiteRecipes/Net_TConv_BN_005/test.recipe b/res/TensorFlowLiteRecipes/Net_TConv_BN_005/test.recipe
index 21607918c..3b227dfb1 100644
--- a/res/TensorFlowLiteRecipes/Net_TConv_BN_005/test.recipe
+++ b/res/TensorFlowLiteRecipes/Net_TConv_BN_005/test.recipe
@@ -102,6 +102,7 @@ operation {
padding: VALID
stride_w: 1
stride_h: 1
+ activation: NONE
}
}
operation {
diff --git a/res/TensorFlowLiteRecipes/Quant_Add_I8_000/test.recipe b/res/TensorFlowLiteRecipes/Quant_Add_I8_000/test.recipe
new file mode 100644
index 000000000..80fb0d1af
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Quant_Add_I8_000/test.recipe
@@ -0,0 +1,66 @@
+operand {
+ name: "x"
+ type: INT8
+ shape {
+ dim: 1
+ dim: 28
+ dim: 28
+ dim: 64
+ }
+ quant {
+ min: -4.73560715
+ max: 5.34916592
+ scale: 0.0395481288
+ zero_point: -8
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operand {
+ name: "x_1"
+ type: INT8
+ shape {
+ dim: 1
+ dim: 28
+ dim: 28
+ dim: 64
+ }
+ quant {
+ min: -5.03376198
+ max: 5.14654779
+ scale: 0.0399227813
+ zero_point: -2
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operand {
+ name: "Identity"
+ type: INT8
+ shape {
+ dim: 1
+ dim: 28
+ dim: 28
+ dim: 64
+ }
+ quant {
+ min: -6.4396615
+ max: 6.40962505
+ scale: 0.0503893606
+ zero_point: 0
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operation {
+ type: "Add"
+ input: "x"
+ input: "x_1"
+ output: "Identity"
+ add_options {
+ activation: NONE
+ }
+}
+input: "x"
+input: "x_1"
+output: "Identity"
diff --git a/res/TensorFlowLiteRecipes/Quant_Add_I8_000/test.rule b/res/TensorFlowLiteRecipes/Quant_Add_I8_000/test.rule
new file mode 100644
index 000000000..8c39b94c4
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Quant_Add_I8_000/test.rule
@@ -0,0 +1,7 @@
+# To check requantization.
+
+RULE "VERIFY_FILE_FORMAT" $(verify_file_format) '=' 1
+
+RULE "IFM1_U8" $(tensor_dtype x) '=' UINT8
+RULE "IFM2_U8" $(tensor_dtype x_1) '=' UINT8
+RULE "OFM_U8" $(tensor_dtype Identity) '=' UINT8
diff --git a/res/TensorFlowLiteRecipes/Quant_AveragePool2D_I8_000/test.recipe b/res/TensorFlowLiteRecipes/Quant_AveragePool2D_I8_000/test.recipe
new file mode 100644
index 000000000..cc5095342
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Quant_AveragePool2D_I8_000/test.recipe
@@ -0,0 +1,51 @@
+operand {
+ name: "x"
+ type: INT8
+ shape {
+ dim: 1
+ dim: 28
+ dim: 28
+ dim: 64
+ }
+ quant {
+ min: -4.91805935
+ max: 4.73869658
+ scale: 0.0378696285
+ zero_point: 2
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operand {
+ name: "Identity"
+ type: INT8
+ shape {
+ dim: 1
+ dim: 14
+ dim: 14
+ dim: 64
+ }
+ quant {
+ min: -4.91805935
+ max: 4.73869658
+ scale: 0.0378696285
+ zero_point: 2
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operation {
+ type: "AveragePool2D"
+ input: "x"
+ output: "Identity"
+ averagepool2d_options {
+ padding: VALID
+ stride_w: 2
+ stride_h: 2
+ filter_width: 2
+ filter_height: 2
+ activation: NONE
+ }
+}
+input: "x"
+output: "Identity"
diff --git a/res/TensorFlowLiteRecipes/Quant_AveragePool2D_I8_000/test.rule b/res/TensorFlowLiteRecipes/Quant_AveragePool2D_I8_000/test.rule
new file mode 100644
index 000000000..35eaa9a53
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Quant_AveragePool2D_I8_000/test.rule
@@ -0,0 +1,6 @@
+# To check requantization.
+
+RULE "VERIFY_FILE_FORMAT" $(verify_file_format) '=' 1
+
+RULE "IFM_U8" $(tensor_dtype x) '=' UINT8
+RULE "OFM_U8" $(tensor_dtype Identity) '=' UINT8
diff --git a/res/TensorFlowLiteRecipes/Quant_Conv_I8_000/test.recipe b/res/TensorFlowLiteRecipes/Quant_Conv_I8_000/test.recipe
new file mode 100644
index 000000000..44ad8ad23
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Quant_Conv_I8_000/test.recipe
@@ -0,0 +1,472 @@
+operand {
+ name: "x"
+ type: INT8
+ shape {
+ dim: 1
+ dim: 28
+ dim: 28
+ dim: 64
+ }
+ quant {
+ min: -4.60775042
+ max: 4.72273636
+ scale: 0.036590144
+ zero_point: -2
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operand {
+ name: "conv2d/Conv2D"
+ type: INT8
+ shape {
+ dim: 64
+ dim: 3
+ dim: 3
+ dim: 64
+ }
+ filler {
+ tag: "gaussian"
+ arg: "0.0"
+ arg: "0.1"
+ }
+ quant {
+ min: -0.0944232419
+ min: -0.0943553224
+ min: -0.0940016955
+ min: -0.0902028382
+ min: -0.0940822735
+ min: -0.0943455622
+ min: -0.0938868895
+ min: -0.0932510793
+ min: -0.0943445265
+ min: -0.0938660875
+ min: -0.0932407603
+ min: -0.0922792107
+ min: -0.090897508
+ min: -0.094613649
+ min: -0.0946459174
+ min: -0.0942868292
+ min: -0.0938613489
+ min: -0.0930051133
+ min: -0.0935952961
+ min: -0.0912109241
+ min: -0.0931911319
+ min: -0.0945508927
+ min: -0.0934816301
+ min: -0.0920401588
+ min: -0.0945732072
+ min: -0.0935128182
+ min: -0.0945002586
+ min: -0.0941293538
+ min: -0.0943162367
+ min: -0.0935421884
+ min: -0.0925261453
+ min: -0.0925333053
+ min: -0.0947286934
+ min: -0.0900891423
+ min: -0.0901428238
+ min: -0.0939482
+ min: -0.0921313837
+ min: -0.0932294279
+ min: -0.0916569456
+ min: -0.0946567059
+ min: -0.0945841148
+ min: -0.0947021097
+ min: -0.092875883
+ min: -0.0915970951
+ min: -0.0944385231
+ min: -0.0938618854
+ min: -0.0934935212
+ min: -0.0932230875
+ min: -0.0930254608
+ min: -0.0945126489
+ min: -0.0945077688
+ min: -0.0938009396
+ min: -0.0940574557
+ min: -0.0939351916
+ min: -0.0946185738
+ min: -0.0913222954
+ min: -0.0927926674
+ min: -0.0934722796
+ min: -0.0944210738
+ min: -0.093838416
+ min: -0.0937703848
+ min: -0.0931927413
+ min: -0.0942146331
+ min: -0.0941971242
+ max: 0.0917563215
+ max: 0.0933615
+ max: 0.0939033106
+ max: 0.0915425941
+ max: 0.0902856588
+ max: 0.0946686193
+ max: 0.0945754126
+ max: 0.09072759
+ max: 0.0944143608
+ max: 0.0940838605
+ max: 0.0927160084
+ max: 0.0920422375
+ max: 0.0943431184
+ max: 0.0938885286
+ max: 0.0936606303
+ max: 0.0936031714
+ max: 0.0919222832
+ max: 0.0942450911
+ max: 0.0936903879
+ max: 0.0942620337
+ max: 0.0930888131
+ max: 0.094434835
+ max: 0.0916963741
+ max: 0.0938658938
+ max: 0.0945749655
+ max: 0.092634663
+ max: 0.0944076553
+ max: 0.0946160257
+ max: 0.0937980711
+ max: 0.093268238
+ max: 0.0944246724
+ max: 0.0931886435
+ max: 0.0947005823
+ max: 0.0921203196
+ max: 0.0944035128
+ max: 0.0937120244
+ max: 0.0928558633
+ max: 0.0943659618
+ max: 0.0924747065
+ max: 0.0925901
+ max: 0.0911629498
+ max: 0.0941480845
+ max: 0.0917054042
+ max: 0.0926568806
+ max: 0.0941145867
+ max: 0.092836
+ max: 0.093148917
+ max: 0.0946854576
+ max: 0.0938850194
+ max: 0.0942198783
+ max: 0.0939895958
+ max: 0.0937283114
+ max: 0.0943206325
+ max: 0.0944009274
+ max: 0.0923624262
+ max: 0.0929848477
+ max: 0.094728522
+ max: 0.0939471
+ max: 0.0935599357
+ max: 0.0942030475
+ max: 0.0937476754
+ max: 0.093198292
+ max: 0.0930417553
+ max: 0.0856469646
+ scale: 0.00074349012
+ scale: 0.000742955308
+ scale: 0.000740170828
+ scale: 0.000720807817
+ scale: 0.000740805292
+ scale: 0.000745422207
+ scale: 0.000744688266
+ scale: 0.00073426048
+ scale: 0.000743420154
+ scale: 0.000740817806
+ scale: 0.000734179222
+ scale: 0.000726608
+ scale: 0.000742859207
+ scale: 0.000744989375
+ scale: 0.000745243451
+ scale: 0.000742415956
+ scale: 0.000739065756
+ scale: 0.000742087315
+ scale: 0.000737719587
+ scale: 0.000742220727
+ scale: 0.000733788416
+ scale: 0.000744495192
+ scale: 0.000736075803
+ scale: 0.000739101553
+ scale: 0.000744684774
+ scale: 0.000736321381
+ scale: 0.000744096527
+ scale: 0.000745008059
+ scale: 0.000742647506
+ scale: 0.00073655264
+ scale: 0.000743501354
+ scale: 0.000733768858
+ scale: 0.000745895202
+ scale: 0.000725356862
+ scale: 0.000743334764
+ scale: 0.000739749637
+ scale: 0.000731148524
+ scale: 0.000743039069
+ scale: 0.000728147279
+ scale: 0.000745328376
+ scale: 0.000744756835
+ scale: 0.000745685888
+ scale: 0.000731306151
+ scale: 0.000729581749
+ scale: 0.000743610435
+ scale: 0.000739069947
+ scale: 0.000736169459
+ scale: 0.000745554804
+ scale: 0.000739252137
+ scale: 0.000744194083
+ scale: 0.000744155666
+ scale: 0.000738590083
+ scale: 0.000742682139
+ scale: 0.000743314391
+ scale: 0.000745028141
+ scale: 0.000732164131
+ scale: 0.000745893863
+ scale: 0.000739740906
+ scale: 0.000743473
+ scale: 0.000741756288
+ scale: 0.00073834951
+ scale: 0.000733844819
+ scale: 0.0007418475
+ scale: 0.000741709664
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operand {
+ name: "conv2d/BiasAdd;conv2d/Conv2D;conv2d/BiasAdd/ReadVariableOp/resource"
+ type: INT32
+ shape {
+ dim: 64
+ }
+ filler {
+ tag: "gaussian"
+ arg: "0.0"
+ arg: "0.1"
+ }
+ quant {
+ scale: 2.72044108e-05
+ scale: 2.71848421e-05
+ scale: 2.70829569e-05
+ scale: 2.63744623e-05
+ scale: 2.71061726e-05
+ scale: 2.72751058e-05
+ scale: 2.72482503e-05
+ scale: 2.68666972e-05
+ scale: 2.72018497e-05
+ scale: 2.7106631e-05
+ scale: 2.68637232e-05
+ scale: 2.65866911e-05
+ scale: 2.7181326e-05
+ scale: 2.72592679e-05
+ scale: 2.72685647e-05
+ scale: 2.71651061e-05
+ scale: 2.70425226e-05
+ scale: 2.71530826e-05
+ scale: 2.69932661e-05
+ scale: 2.71579629e-05
+ scale: 2.68494241e-05
+ scale: 2.72411871e-05
+ scale: 2.69331194e-05
+ scale: 2.70438322e-05
+ scale: 2.72481229e-05
+ scale: 2.69421053e-05
+ scale: 2.72265988e-05
+ scale: 2.72599518e-05
+ scale: 2.71735789e-05
+ scale: 2.69505672e-05
+ scale: 2.72048219e-05
+ scale: 2.68487074e-05
+ scale: 2.72924135e-05
+ scale: 2.65409126e-05
+ scale: 2.71987265e-05
+ scale: 2.70675464e-05
+ scale: 2.67528303e-05
+ scale: 2.71879071e-05
+ scale: 2.66430143e-05
+ scale: 2.72716734e-05
+ scale: 2.72507605e-05
+ scale: 2.72847537e-05
+ scale: 2.67585965e-05
+ scale: 2.66955012e-05
+ scale: 2.72088128e-05
+ scale: 2.70426754e-05
+ scale: 2.69365464e-05
+ scale: 2.72799571e-05
+ scale: 2.7049342e-05
+ scale: 2.72301695e-05
+ scale: 2.72287634e-05
+ scale: 2.70251167e-05
+ scale: 2.71748468e-05
+ scale: 2.71979807e-05
+ scale: 2.72606867e-05
+ scale: 2.67899904e-05
+ scale: 2.72923644e-05
+ scale: 2.70672263e-05
+ scale: 2.72037851e-05
+ scale: 2.71409699e-05
+ scale: 2.70163146e-05
+ scale: 2.68514868e-05
+ scale: 2.71443078e-05
+ scale: 2.71392637e-05
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operand {
+ name: "Identity"
+ type: INT8
+ shape {
+ dim: 1
+ dim: 26
+ dim: 26
+ dim: 64
+ }
+ quant {
+ min: -4.71095943
+ max: 4.83075953
+ scale: 0.037418507
+ zero_point: -2
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operation {
+ type: "Conv2D"
+ input: "x"
+ input: "conv2d/Conv2D"
+ input: "conv2d/BiasAdd;conv2d/Conv2D;conv2d/BiasAdd/ReadVariableOp/resource"
+ output: "Identity"
+ conv2d_options {
+ padding: VALID
+ stride_w: 1
+ stride_h: 1
+ activation: NONE
+ dilation_w_factor: 1
+ dilation_h_factor: 1
+ }
+}
+input: "x"
+output: "Identity"
diff --git a/res/TensorFlowLiteRecipes/Quant_Conv_I8_000/test.rule b/res/TensorFlowLiteRecipes/Quant_Conv_I8_000/test.rule
new file mode 100644
index 000000000..fa7b908f4
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Quant_Conv_I8_000/test.rule
@@ -0,0 +1,8 @@
+# To check requantization.
+
+RULE "VERIFY_FILE_FORMAT" $(verify_file_format) '=' 1
+
+RULE "IFM_U8" $(tensor_dtype x) '=' UINT8
+RULE "WGT_U8" $(tensor_dtype conv2d/Conv2D) '=' UINT8
+RULE "BIAS_S32" $(tensor_dtype conv2d/BiasAdd\;conv2d/Conv2D\;conv2d/BiasAdd/ReadVariableOp/resource) '=' INT32
+RULE "OFM_U8" $(tensor_dtype Identity) '=' UINT8
diff --git a/res/TensorFlowLiteRecipes/Quant_DepthwiseConv2D_I8_000/test.recipe b/res/TensorFlowLiteRecipes/Quant_DepthwiseConv2D_I8_000/test.recipe
new file mode 100644
index 000000000..6fa6e98b1
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Quant_DepthwiseConv2D_I8_000/test.recipe
@@ -0,0 +1,473 @@
+operand {
+ name: "x"
+ type: INT8
+ shape {
+ dim: 1
+ dim: 28
+ dim: 28
+ dim: 64
+ }
+ quant {
+ min: -4.64391708
+ max: 4.84164238
+ scale: 0.0371982716
+ zero_point: -3
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operand {
+ name: "depthwise_conv2d/depthwise"
+ type: INT8
+ shape {
+ dim: 1
+ dim: 3
+ dim: 3
+ dim: 64
+ }
+ filler {
+ tag: "gaussian"
+ arg: "0.0"
+ arg: "0.1"
+ }
+ quant {
+ min: -0.063326925
+ min: -0.0634795
+ min: -0.0753154755
+ min: -0.0825628936
+ min: -0.100263909
+ min: -0.0518069938
+ min: -0.0903094783
+ min: -0.092050083
+ min: -0.0861446783
+ min: -0.0868664607
+ min: -0.0805943534
+ min: -0.0630288422
+ min: -0.0603802204
+ min: -0.0894295871
+ min: -0.0806457847
+ min: -0.08705163
+ min: -0.0955024436
+ min: -0.099676609
+ min: -0.0426661745
+ min: -0.100863345
+ min: -0.0732110441
+ min: -0.0957087874
+ min: -0.0984382555
+ min: -0.0870531276
+ min: -0.0588906072
+ min: -0.0985565707
+ min: -0.0667493939
+ min: -0.0315393284
+ min: -0.0872938633
+ min: -0.0947047919
+ min: -0.0988249257
+ min: -0.0945888236
+ min: -0.0884424895
+ min: -0.0674908608
+ min: -0.0691238195
+ min: -0.0973802432
+ min: -0.0970137119
+ min: -0.0648144335
+ min: -0.0792933181
+ min: -0.0928001404
+ min: -0.0429098979
+ min: -0.0946487263
+ min: -0.0911387801
+ min: -0.0989532098
+ min: -0.041106537
+ min: -0.0955499113
+ min: -0.0979051739
+ min: -0.0843721703
+ min: -0.0769490227
+ min: -0.0908443704
+ min: -0.0900151655
+ min: -0.100871772
+ min: -0.0811569467
+ min: -0.0867079645
+ min: -0.0810551718
+ min: -0.0915141478
+ min: -0.0988522843
+ min: -0.0506756492
+ min: -0.0828623697
+ min: -0.0969022587
+ min: -0.0862472728
+ min: -0.0536583066
+ min: -0.0739349052
+ min: 0.0297371298
+ max: 0.0629539043
+ max: 0.081167981
+ max: 0.0732295811
+ max: 0.0943298787
+ max: 0.0894318074
+ max: 0.0948470086
+ max: 0.0968847275
+ max: 0.0914845169
+ max: 0.0937000513
+ max: 0.059604913
+ max: 0.0977034122
+ max: 0.0998425633
+ max: 0.0968779624
+ max: 0.0188128203
+ max: 0.0933915377
+ max: 0.058697015
+ max: 0.0965367705
+ max: 0.0620942265
+ max: 0.098770529
+ max: 0.0851371
+ max: 0.0981955677
+ max: 0.059944734
+ max: 0.0692644
+ max: 0.0846596062
+ max: 0.0562474579
+ max: 0.0516051352
+ max: 0.0457287
+ max: 0.088056
+ max: 0.0738085508
+ max: 0.0320325792
+ max: 0.0874649584
+ max: 0.0846493095
+ max: 0.06501019
+ max: 0.0962834805
+ max: 0.0976130068
+ max: 0.0987761915
+ max: 0.0971763879
+ max: 0.0984461755
+ max: 0.0951509
+ max: 0.097969681
+ max: 0.0811607093
+ max: 0.0462665409
+ max: 0.100696355
+ max: 0.0861465335
+ max: 0.0922105
+ max: 0.0879219174
+ max: 0.0897164643
+ max: 0.0870749801
+ max: 0.0918415785
+ max: 0.0730088204
+ max: 0.0392846316
+ max: 0.0920975059
+ max: 0.042890057
+ max: 0.0462249964
+ max: 0.0784825087
+ max: 0.0663191676
+ max: 0.0893450826
+ max: 0.0812896937
+ max: 0.0611626357
+ max: 0.0788473934
+ max: 0.0721678585
+ max: 0.0912485719
+ max: 0.0942054689
+ max: 0.0807732195
+ scale: 0.000498637208
+ scale: 0.000639117963
+ scale: 0.000593035249
+ scale: 0.000742754957
+ scale: 0.000789479585
+ scale: 0.000746826816
+ scale: 0.000762871874
+ scale: 0.000724803831
+ scale: 0.000737795664
+ scale: 0.000683987862
+ scale: 0.000769318198
+ scale: 0.000786161923
+ scale: 0.000762818614
+ scale: 0.00070417
+ scale: 0.000735366426
+ scale: 0.000685445906
+ scale: 0.000760132039
+ scale: 0.000784855161
+ scale: 0.000777720707
+ scale: 0.000794199586
+ scale: 0.000773193431
+ scale: 0.00075361249
+ scale: 0.000775104389
+ scale: 0.000685457722
+ scale: 0.000463705568
+ scale: 0.000776036
+ scale: 0.000525585783
+ scale: 0.00069335429
+ scale: 0.000687353255
+ scale: 0.000745707
+ scale: 0.000778149
+ scale: 0.000744793913
+ scale: 0.000696397561
+ scale: 0.00075813767
+ scale: 0.000768606376
+ scale: 0.000777765294
+ scale: 0.000765168399
+ scale: 0.000775166729
+ scale: 0.000749219733
+ scale: 0.000771414838
+ scale: 0.000639060687
+ scale: 0.00074526557
+ scale: 0.000792884675
+ scale: 0.000779159134
+ scale: 0.000726066937
+ scale: 0.000752361491
+ scale: 0.00077090686
+ scale: 0.000685629784
+ scale: 0.000723162
+ scale: 0.00071531
+ scale: 0.000708780834
+ scale: 0.000794265943
+ scale: 0.000639031059
+ scale: 0.00068273989
+ scale: 0.000638229714
+ scale: 0.000720583834
+ scale: 0.000778364425
+ scale: 0.000640076352
+ scale: 0.000652459625
+ scale: 0.000763009884
+ scale: 0.000679112389
+ scale: 0.000718492665
+ scale: 0.000741775322
+ scale: 0.000636009616
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ quantized_dimension: 3
+ }
+ is_variable: false
+}
+operand {
+ name: "depthwise_conv2d/BiasAdd;depthwise_conv2d/depthwise;depthwise_conv2d/BiasAdd/ReadVariableOp/resource"
+ type: INT32
+ shape {
+ dim: 64
+ }
+ filler {
+ tag: "gaussian"
+ arg: "0.0"
+ arg: "0.1"
+ }
+ quant {
+ scale: 1.85484423e-05
+ scale: 2.37740842e-05
+ scale: 2.20598868e-05
+ scale: 2.76292012e-05
+ scale: 2.93672765e-05
+ scale: 2.77806666e-05
+ scale: 2.83775153e-05
+ scale: 2.69614502e-05
+ scale: 2.74447229e-05
+ scale: 2.5443167e-05
+ scale: 2.86173072e-05
+ scale: 2.92438654e-05
+ scale: 2.83755344e-05
+ scale: 2.61939058e-05
+ scale: 2.73543592e-05
+ scale: 2.54974038e-05
+ scale: 2.82755973e-05
+ scale: 2.91952547e-05
+ scale: 2.89298659e-05
+ scale: 2.95428526e-05
+ scale: 2.87614585e-05
+ scale: 2.80330823e-05
+ scale: 2.88325427e-05
+ scale: 2.54978422e-05
+ scale: 1.72490454e-05
+ scale: 2.88671981e-05
+ scale: 1.95508819e-05
+ scale: 2.57915817e-05
+ scale: 2.55683535e-05
+ scale: 2.77390118e-05
+ scale: 2.89457985e-05
+ scale: 2.77050458e-05
+ scale: 2.59047865e-05
+ scale: 2.82014116e-05
+ scale: 2.85908282e-05
+ scale: 2.89315249e-05
+ scale: 2.84629423e-05
+ scale: 2.8834862e-05
+ scale: 2.78696789e-05
+ scale: 2.86952982e-05
+ scale: 2.37719523e-05
+ scale: 2.77225918e-05
+ scale: 2.949394e-05
+ scale: 2.89833733e-05
+ scale: 2.70084347e-05
+ scale: 2.79865471e-05
+ scale: 2.86764025e-05
+ scale: 2.55042432e-05
+ scale: 2.69003776e-05
+ scale: 2.66082952e-05
+ scale: 2.63654219e-05
+ scale: 2.9545321e-05
+ scale: 2.377085e-05
+ scale: 2.53967446e-05
+ scale: 2.37410422e-05
+ scale: 2.68044732e-05
+ scale: 2.89538111e-05
+ scale: 2.38097346e-05
+ scale: 2.427037e-05
+ scale: 2.83826485e-05
+ scale: 2.52618065e-05
+ scale: 2.6726686e-05
+ scale: 2.75927596e-05
+ scale: 2.36584583e-05
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operand {
+ name: "Identity"
+ type: INT8
+ shape {
+ dim: 1
+ dim: 26
+ dim: 26
+ dim: 64
+ }
+ quant {
+ min: -1.07687819
+ max: 1.02835441
+ scale: 0.0082558142
+ zero_point: 2
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operation {
+ type: "DepthwiseConv2D"
+ input: "x"
+ input: "depthwise_conv2d/depthwise"
+ input: "depthwise_conv2d/BiasAdd;depthwise_conv2d/depthwise;depthwise_conv2d/BiasAdd/ReadVariableOp/resource"
+ output: "Identity"
+ depthwiseconv2d_options {
+ padding: VALID
+ stride_w: 1
+ stride_h: 1
+ depth_multiplier: 1
+ activation: NONE
+ dilation_w_factor: 1
+ dilation_h_factor: 1
+ }
+}
+input: "x"
+output: "Identity"
diff --git a/res/TensorFlowLiteRecipes/Quant_DepthwiseConv2D_I8_000/test.rule b/res/TensorFlowLiteRecipes/Quant_DepthwiseConv2D_I8_000/test.rule
new file mode 100644
index 000000000..2c2a2a762
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Quant_DepthwiseConv2D_I8_000/test.rule
@@ -0,0 +1,8 @@
+# To check requantization.
+
+RULE "VERIFY_FILE_FORMAT" $(verify_file_format) '=' 1
+
+RULE "IFM_U8" $(tensor_dtype x) '=' UINT8
+RULE "WGT_U8" $(tensor_dtype depthwise_conv2d/depthwise) '=' UINT8
+RULE "BIAS_S32" $(tensor_dtype depthwise_conv2d/BiasAdd\;depthwise_conv2d/depthwise\;depthwise_conv2d/BiasAdd/ReadVariableOp/resource) '=' INT32
+RULE "OFM_U8" $(tensor_dtype Identity) '=' UINT8
diff --git a/res/TensorFlowLiteRecipes/Quant_MaxPool2D_I8_000/test.recipe b/res/TensorFlowLiteRecipes/Quant_MaxPool2D_I8_000/test.recipe
new file mode 100644
index 000000000..23717132e
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Quant_MaxPool2D_I8_000/test.recipe
@@ -0,0 +1,51 @@
+operand {
+ name: "x"
+ type: INT8
+ shape {
+ dim: 1
+ dim: 28
+ dim: 28
+ dim: 128
+ }
+ quant {
+ min: -4.71396
+ max: 4.72839499
+ scale: 0.0370288454
+ zero_point: -1
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operand {
+ name: "Identity"
+ type: INT8
+ shape {
+ dim: 1
+ dim: 14
+ dim: 14
+ dim: 128
+ }
+ quant {
+ min: -4.71396
+ max: 4.72839499
+ scale: 0.0370288454
+ zero_point: -1
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operation {
+ type: "MaxPool2D"
+ input: "x"
+ output: "Identity"
+ maxpool2d_options {
+ padding: VALID
+ stride_w: 2
+ stride_h: 2
+ filter_width: 2
+ filter_height: 2
+ activation: NONE
+ }
+}
+input: "x"
+output: "Identity"
diff --git a/res/TensorFlowLiteRecipes/Quant_MaxPool2D_I8_000/test.rule b/res/TensorFlowLiteRecipes/Quant_MaxPool2D_I8_000/test.rule
new file mode 100644
index 000000000..35eaa9a53
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Quant_MaxPool2D_I8_000/test.rule
@@ -0,0 +1,6 @@
+# To check requantization.
+
+RULE "VERIFY_FILE_FORMAT" $(verify_file_format) '=' 1
+
+RULE "IFM_U8" $(tensor_dtype x) '=' UINT8
+RULE "OFM_U8" $(tensor_dtype Identity) '=' UINT8
diff --git a/res/TensorFlowLiteRecipes/Quant_Mean_I8_000/test.recipe b/res/TensorFlowLiteRecipes/Quant_Mean_I8_000/test.recipe
new file mode 100644
index 000000000..bccdff277
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Quant_Mean_I8_000/test.recipe
@@ -0,0 +1,63 @@
+operand {
+ name: "x"
+ type: INT8
+ shape {
+ dim: 1
+ dim: 7
+ dim: 7
+ dim: 128
+ }
+ quant {
+ min: -4.52155876
+ max: 4.65688181
+ scale: 0.0359938815
+ zero_point: -2
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operand {
+ name: "Mean/reduction_indices"
+ type: INT32
+ shape {
+ dim: 2
+ }
+ filler {
+ tag: "explicit"
+ arg: "1"
+ arg: "2"
+ }
+ quant {
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operand {
+ name: "Identity"
+ type: INT8
+ shape {
+ dim: 1
+ dim: 1
+ dim: 1
+ dim: 128
+ }
+ quant {
+ min: -0.548125625
+ max: 0.485593677
+ scale: 0.0040538013
+ zero_point: 7
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operation {
+ type: "Mean"
+ input: "x"
+ input: "Mean/reduction_indices"
+ output: "Identity"
+ mean_options {
+ keep_dims: true
+ }
+}
+input: "x"
+output: "Identity"
diff --git a/res/TensorFlowLiteRecipes/Quant_Mean_I8_000/test.rule b/res/TensorFlowLiteRecipes/Quant_Mean_I8_000/test.rule
new file mode 100644
index 000000000..89610199f
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Quant_Mean_I8_000/test.rule
@@ -0,0 +1,7 @@
+# To check requantization.
+
+RULE "VERIFY_FILE_FORMAT" $(verify_file_format) '=' 1
+
+RULE "IFM_U8" $(tensor_dtype x) '=' UINT8
+RULE "AXIS_S32" $(tensor_dtype Mean/reduction_indices) '=' INT32
+RULE "OFM_U8" $(tensor_dtype Identity) '=' UINT8
diff --git a/res/TensorFlowLiteRecipes/Quant_Mul_I8_000/test.recipe b/res/TensorFlowLiteRecipes/Quant_Mul_I8_000/test.recipe
new file mode 100644
index 000000000..af37f4a5e
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Quant_Mul_I8_000/test.recipe
@@ -0,0 +1,66 @@
+operand {
+ name: "x"
+ type: INT8
+ shape {
+ dim: 1
+ dim: 28
+ dim: 28
+ dim: 64
+ }
+ quant {
+ min: -4.91511106
+ max: 4.63654947
+ scale: 0.0374574922
+ zero_point: 3
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operand {
+ name: "x_1"
+ type: INT8
+ shape {
+ dim: 1
+ dim: 28
+ dim: 28
+ dim: 64
+ }
+ quant {
+ min: -4.70411062
+ max: 4.48266
+ scale: 0.0360265523
+ zero_point: 3
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operand {
+ name: "Identity"
+ type: INT8
+ shape {
+ dim: 1
+ dim: 28
+ dim: 28
+ dim: 64
+ }
+ quant {
+ min: -10.2211161
+ max: 10.4154072
+ scale: 0.0809275433
+ zero_point: -2
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operation {
+ type: "Mul"
+ input: "x"
+ input: "x_1"
+ output: "Identity"
+ mul_options {
+ activation: NONE
+ }
+}
+input: "x"
+input: "x_1"
+output: "Identity"
diff --git a/res/TensorFlowLiteRecipes/Quant_Mul_I8_000/test.rule b/res/TensorFlowLiteRecipes/Quant_Mul_I8_000/test.rule
new file mode 100644
index 000000000..8c39b94c4
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Quant_Mul_I8_000/test.rule
@@ -0,0 +1,7 @@
+# To check requantization.
+
+RULE "VERIFY_FILE_FORMAT" $(verify_file_format) '=' 1
+
+RULE "IFM1_U8" $(tensor_dtype x) '=' UINT8
+RULE "IFM2_U8" $(tensor_dtype x_1) '=' UINT8
+RULE "OFM_U8" $(tensor_dtype Identity) '=' UINT8
diff --git a/res/TensorFlowLiteRecipes/Quant_PRelu_I8_000/test.recipe b/res/TensorFlowLiteRecipes/Quant_PRelu_I8_000/test.recipe
new file mode 100644
index 000000000..2b8caa930
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Quant_PRelu_I8_000/test.recipe
@@ -0,0 +1,66 @@
+operand {
+ name: "x"
+ type: INT8
+ shape {
+ dim: 1
+ dim: 28
+ dim: 28
+ dim: 64
+ }
+ quant {
+ min: -4.600914
+ max: 4.44562244
+ scale: 0.0354766138
+ zero_point: 2
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operand {
+ name: "p_re_lu/add;p_re_lu/Relu;p_re_lu/Neg_1;p_re_lu/Relu_1;p_re_lu/mul"
+ type: INT8
+ shape {
+ dim: 1
+ dim: 1
+ dim: 64
+ }
+ filler {
+ tag: "gaussian"
+ arg: "0.0"
+ arg: "0.1"
+ }
+ quant {
+ min: -0.391680807
+ max: 0.391578436
+ scale: 0.00308410078
+ zero_point: 0
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operand {
+ name: "Identity"
+ type: INT8
+ shape {
+ dim: 1
+ dim: 28
+ dim: 28
+ dim: 64
+ }
+ quant {
+ min: -1.45854628
+ max: 4.44562244
+ scale: 0.0231536031
+ zero_point: -65
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operation {
+ type: "PRelu"
+ input: "x"
+ input: "p_re_lu/add;p_re_lu/Relu;p_re_lu/Neg_1;p_re_lu/Relu_1;p_re_lu/mul"
+ output: "Identity"
+}
+input: "x"
+output: "Identity"
diff --git a/res/TensorFlowLiteRecipes/Quant_PRelu_I8_000/test.rule b/res/TensorFlowLiteRecipes/Quant_PRelu_I8_000/test.rule
new file mode 100644
index 000000000..e55dfba9c
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Quant_PRelu_I8_000/test.rule
@@ -0,0 +1,7 @@
+# To check requantization.
+
+RULE "VERIFY_FILE_FORMAT" $(verify_file_format) '=' 1
+
+RULE "IFM_U8" $(tensor_dtype x) '=' UINT8
+RULE "ALPHA_U8" $(tensor_dtype p_re_lu/add\;p_re_lu/Relu\;p_re_lu/Neg_1\;p_re_lu/Relu_1\;p_re_lu/mul) '=' UINT8
+RULE "OFM_U8" $(tensor_dtype Identity) '=' UINT8
diff --git a/res/TensorFlowLiteRecipes/Quant_ReLU_I8_000/test.recipe b/res/TensorFlowLiteRecipes/Quant_ReLU_I8_000/test.recipe
new file mode 100644
index 000000000..0cce090c9
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Quant_ReLU_I8_000/test.recipe
@@ -0,0 +1,43 @@
+operand {
+ name: "x"
+ type: INT8
+ shape {
+ dim: 1
+ dim: 28
+ dim: 28
+ dim: 64
+ }
+ quant {
+ min: -4.62792873
+ max: 4.3443079
+ scale: 0.0351852402
+ zero_point: 4
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operand {
+ name: "Identity"
+ type: INT8
+ shape {
+ dim: 1
+ dim: 28
+ dim: 28
+ dim: 64
+ }
+ quant {
+ min: 0
+ max: 4.3443079
+ scale: 0.0170365013
+ zero_point: -128
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operation {
+ type: "ReLU"
+ input: "x"
+ output: "Identity"
+}
+input: "x"
+output: "Identity"
diff --git a/res/TensorFlowLiteRecipes/Quant_ReLU_I8_000/test.rule b/res/TensorFlowLiteRecipes/Quant_ReLU_I8_000/test.rule
new file mode 100644
index 000000000..35eaa9a53
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Quant_ReLU_I8_000/test.rule
@@ -0,0 +1,6 @@
+# To check requantization.
+
+RULE "VERIFY_FILE_FORMAT" $(verify_file_format) '=' 1
+
+RULE "IFM_U8" $(tensor_dtype x) '=' UINT8
+RULE "OFM_U8" $(tensor_dtype Identity) '=' UINT8
diff --git a/res/TensorFlowLiteRecipes/Quant_TransposeConv_000/test.recipe b/res/TensorFlowLiteRecipes/Quant_TransposeConv_000/test.recipe
index c281b0482..9462e1351 100644
--- a/res/TensorFlowLiteRecipes/Quant_TransposeConv_000/test.recipe
+++ b/res/TensorFlowLiteRecipes/Quant_TransposeConv_000/test.recipe
@@ -43,6 +43,7 @@ operation {
padding: SAME
stride_w: 1
stride_h: 1
+ activation: NONE
}
input: "out_shape"
input: "ker"
diff --git a/res/TensorFlowLiteRecipes/Quant_TransposeConv_001/test.recipe b/res/TensorFlowLiteRecipes/Quant_TransposeConv_001/test.recipe
index c281b0482..9462e1351 100644
--- a/res/TensorFlowLiteRecipes/Quant_TransposeConv_001/test.recipe
+++ b/res/TensorFlowLiteRecipes/Quant_TransposeConv_001/test.recipe
@@ -43,6 +43,7 @@ operation {
padding: SAME
stride_w: 1
stride_h: 1
+ activation: NONE
}
input: "out_shape"
input: "ker"
diff --git a/res/TensorFlowLiteRecipes/Quant_TransposeConv_I8_000/test.recipe b/res/TensorFlowLiteRecipes/Quant_TransposeConv_I8_000/test.recipe
new file mode 100644
index 000000000..12a5a34be
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Quant_TransposeConv_I8_000/test.recipe
@@ -0,0 +1,344 @@
+operand {
+ name: "x"
+ type: INT8
+ shape {
+ dim: 1
+ dim: 28
+ dim: 28
+ dim: 64
+ }
+ quant {
+ min: -4.60648251
+ max: 4.56543779
+ scale: 0.0359683186
+ zero_point: 0
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operand {
+ name: "conv2d_transpose/stack"
+ type: INT32
+ shape {
+ dim: 4
+ }
+ filler {
+ tag: "explicit"
+ arg: "1"
+ arg: "30"
+ arg: "30"
+ arg: "64"
+ }
+ quant {
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operand {
+ name: "conv2d_transpose/conv2d_transpose"
+ type: INT8
+ shape {
+ dim: 64
+ dim: 3
+ dim: 3
+ dim: 64
+ }
+ filler {
+ tag: "gaussian"
+ arg: "0.0"
+ arg: "0.1"
+ }
+ quant {
+ min: -0.0946341679
+ min: -0.0944282487
+ min: -0.0918895602
+ min: -0.0925355926
+ min: -0.0947051644
+ min: -0.0941944346
+ min: -0.0941459388
+ min: -0.0919710547
+ min: -0.0916045085
+ min: -0.093310751
+ min: -0.0928586572
+ min: -0.0935951397
+ min: -0.0942160562
+ min: -0.0933434889
+ min: -0.0935866162
+ min: -0.0925118327
+ min: -0.0942456797
+ min: -0.0939968601
+ min: -0.0924739465
+ min: -0.0941662267
+ min: -0.087930195
+ min: -0.0947148651
+ min: -0.0943328366
+ min: -0.0936802849
+ min: -0.0942436531
+ min: -0.0941923857
+ min: -0.0940833613
+ min: -0.0932623446
+ min: -0.0930994451
+ min: -0.0943730548
+ min: -0.0884840712
+ min: -0.0939643234
+ min: -0.0940853506
+ min: -0.0935710147
+ min: -0.0936997607
+ min: -0.0912955627
+ min: -0.0921618789
+ min: -0.0947207361
+ min: -0.0931588039
+ min: -0.0941777378
+ min: -0.0935421512
+ min: -0.09219338
+ min: -0.0944892615
+ min: -0.0936101824
+ min: -0.0937219635
+ min: -0.0916510522
+ min: -0.0941754729
+ min: -0.0943513513
+ min: -0.0933411643
+ min: -0.0934003219
+ min: -0.0936945155
+ min: -0.0943120122
+ min: -0.0936696753
+ min: -0.0941288397
+ min: -0.0931984335
+ min: -0.0946868435
+ min: -0.0931827351
+ min: -0.0937825665
+ min: -0.0920807496
+ min: -0.0920289457
+ min: -0.0932372659
+ min: -0.0933243334
+ min: -0.091677241
+ min: -0.0938237533
+ max: 0.0929114074
+ max: 0.0939644054
+ max: 0.0936235785
+ max: 0.0945259407
+ max: 0.091929324
+ max: 0.0927724242
+ max: 0.0939807221
+ max: 0.0932361633
+ max: 0.0926983431
+ max: 0.0941318944
+ max: 0.0939000174
+ max: 0.0943209827
+ max: 0.0936219618
+ max: 0.0933490321
+ max: 0.0942894742
+ max: 0.0940931812
+ max: 0.0910203531
+ max: 0.0894439071
+ max: 0.0919351205
+ max: 0.0924752355
+ max: 0.09339872
+ max: 0.0942701921
+ max: 0.0933261067
+ max: 0.0920859501
+ max: 0.0946150199
+ max: 0.0933252722
+ max: 0.0941924453
+ max: 0.0936042666
+ max: 0.0931428894
+ max: 0.0926085934
+ max: 0.0915477723
+ max: 0.0934655741
+ max: 0.0947353616
+ max: 0.0938620269
+ max: 0.0939659476
+ max: 0.0943774134
+ max: 0.0933601633
+ max: 0.0943998545
+ max: 0.0934786722
+ max: 0.0935663804
+ max: 0.0902687311
+ max: 0.0915351138
+ max: 0.0941802114
+ max: 0.0939741656
+ max: 0.0947180837
+ max: 0.0943731889
+ max: 0.0931445807
+ max: 0.0917655453
+ max: 0.0940534249
+ max: 0.0941507071
+ max: 0.093019031
+ max: 0.0945132151
+ max: 0.0944205299
+ max: 0.0932926387
+ max: 0.0919418409
+ max: 0.0931737125
+ max: 0.0918817222
+ max: 0.0942185298
+ max: 0.094377391
+ max: 0.0927698091
+ max: 0.0935381278
+ max: 0.0942255259
+ max: 0.0910803
+ max: 0.0942931473
+ scale: 0.000745150901
+ scale: 0.000743529527
+ scale: 0.000737193506
+ scale: 0.000744298741
+ scale: 0.000745709927
+ scale: 0.000741688476
+ scale: 0.000741306576
+ scale: 0.000734143
+ scale: 0.000729908235
+ scale: 0.00074119604
+ scale: 0.00073937024
+ scale: 0.000742684875
+ scale: 0.000741858734
+ scale: 0.000735031732
+ scale: 0.000742436794
+ scale: 0.000740891206
+ scale: 0.000742092
+ scale: 0.00074013276
+ scale: 0.000728141284
+ scale: 0.000741466356
+ scale: 0.000735423
+ scale: 0.000745786354
+ scale: 0.00074277824
+ scale: 0.00073764
+ scale: 0.000745000143
+ scale: 0.000741672353
+ scale: 0.000741672819
+ scale: 0.000737041468
+ scale: 0.000733408553
+ scale: 0.000743094948
+ scale: 0.00072084862
+ scale: 0.000739876588
+ scale: 0.000745947706
+ scale: 0.000739071053
+ scale: 0.000739889336
+ scale: 0.000743129232
+ scale: 0.000735119393
+ scale: 0.000745832571
+ scale: 0.00073605252
+ scale: 0.000741557
+ scale: 0.000736552349
+ scale: 0.000725932128
+ scale: 0.000744009914
+ scale: 0.000739954063
+ scale: 0.000745811674
+ scale: 0.000743096
+ scale: 0.000741539174
+ scale: 0.00074292405
+ scale: 0.000740578165
+ scale: 0.000741344178
+ scale: 0.000737752067
+ scale: 0.000744198565
+ scale: 0.000743468758
+ scale: 0.000741171942
+ scale: 0.000733845925
+ scale: 0.000745565689
+ scale: 0.000733722351
+ scale: 0.000741878175
+ scale: 0.000743129058
+ scale: 0.000730470929
+ scale: 0.000736520684
+ scale: 0.000741933298
+ scale: 0.000721868
+ scale: 0.000742465723
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ zero_point: 0
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operand {
+ name: "Identity"
+ type: INT8
+ shape {
+ dim: 1
+ dim: 30
+ dim: 30
+ dim: 64
+ }
+ quant {
+ min: -4.55380917
+ max: 4.73831749
+ scale: 0.0364397131
+ zero_point: -3
+ quantized_dimension: 0
+ }
+ is_variable: false
+}
+operation {
+ type: "TransposeConv"
+ input: "conv2d_transpose/stack"
+ input: "conv2d_transpose/conv2d_transpose"
+ input: "x"
+ output: "Identity"
+ transpose_conv_options {
+ padding: VALID
+ stride_w: 1
+ stride_h: 1
+ activation: NONE
+ }
+}
+input: "x"
+output: "Identity"
diff --git a/res/TensorFlowLiteRecipes/Quant_TransposeConv_I8_000/test.rule b/res/TensorFlowLiteRecipes/Quant_TransposeConv_I8_000/test.rule
new file mode 100644
index 000000000..a3ac17450
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/Quant_TransposeConv_I8_000/test.rule
@@ -0,0 +1,8 @@
+# To check requantization.
+
+RULE "VERIFY_FILE_FORMAT" $(verify_file_format) '=' 1
+
+RULE "IFM_U8" $(tensor_dtype x) '=' UINT8
+RULE "INPUT_SIZE_S32" $(tensor_dtype conv2d_transpose/stack) '=' INT32
+RULE "WGT_U8" $(tensor_dtype conv2d_transpose/conv2d_transpose) '=' UINT8
+RULE "OFM_U8" $(tensor_dtype Identity) '=' UINT8
diff --git a/res/TensorFlowLiteRecipes/REGRESS_ONNX_Mul_Mul_000/test.recipe b/res/TensorFlowLiteRecipes/REGRESS_ONNX_Mul_Mul_000/test.recipe
new file mode 100644
index 000000000..a3a8a2672
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/REGRESS_ONNX_Mul_Mul_000/test.recipe
@@ -0,0 +1,88 @@
+operand {
+ name: "Input"
+ type: FLOAT32
+ shape {
+ dim: 1
+ dim: 3
+ dim: 32
+ dim: 32
+ }
+}
+operand {
+ name: "Const"
+ type: FLOAT32
+ shape {
+ dim: 1
+ }
+ filler {
+ tag: "explicit"
+ arg: "1"
+ }
+}
+operand {
+ name: "Mul1"
+ type: FLOAT32
+ shape {
+ dim: 1
+ dim: 3
+ dim: 32
+ dim: 32
+ }
+}
+operand {
+ name: "ShapeConst"
+ type: INT32
+ shape {
+ dim: 3
+ }
+ filler {
+ tag: "explicit"
+ arg: "3"
+ arg: "32"
+ arg: "32"
+ }
+}
+operand {
+ name: "Reshape"
+ type: FLOAT32
+ shape {
+ dim: 3
+ dim: 32
+ dim: 32
+ }
+}
+operand {
+ name: "Mul2"
+ type: FLOAT32
+ shape {
+ dim: 3
+ dim: 32
+ dim: 32
+ }
+}
+operation {
+ type: "Mul"
+ input: "Input"
+ input: "Const"
+ output: "Mul1"
+ mul_options {
+ activation: NONE
+ }
+}
+operation {
+ type: "Reshape"
+ input: "Mul1"
+ input: "ShapeConst"
+ output: "Reshape"
+}
+operation {
+ type: "Mul"
+ input: "Reshape"
+ input: "Const"
+ output: "Mul2"
+ mul_options {
+ activation: NONE
+ }
+}
+input: "Input"
+output: "Mul2"
diff --git a/res/TensorFlowLiteRecipes/REGRESS_ONNX_Mul_Mul_000/test.rule b/res/TensorFlowLiteRecipes/REGRESS_ONNX_Mul_Mul_000/test.rule
new file mode 100644
index 000000000..9ad8e9fb3
--- /dev/null
+++ b/res/TensorFlowLiteRecipes/REGRESS_ONNX_Mul_Mul_000/test.rule
@@ -0,0 +1,7 @@
+# To check NCHW to NHWC conversion is OK
+
+RULE "VERIFY_FILE_FORMAT" $(verify_file_format) '=' 1
+
+RULE "MUL_EXIST" $(op_count MUL) '=' 2
+RULE "RESHAPE_EXIST" $(op_count RESHAPE) '=' 1
+RULE "TRANSPOSE" $(op_count TRANSPOSE) '=' 2
diff --git a/res/TensorFlowLiteRecipes/TransposeConv_000/test.recipe b/res/TensorFlowLiteRecipes/TransposeConv_000/test.recipe
index 1313e2683..4e49b2dfd 100644
--- a/res/TensorFlowLiteRecipes/TransposeConv_000/test.recipe
+++ b/res/TensorFlowLiteRecipes/TransposeConv_000/test.recipe
@@ -34,6 +34,7 @@ operation {
padding: SAME
stride_w: 1
stride_h: 1
+ activation: NONE
}
input: "out_shape"
input: "ker"
diff --git a/res/TensorFlowLiteRecipes/TransposeConv_001/test.recipe b/res/TensorFlowLiteRecipes/TransposeConv_001/test.recipe
index ad76100d2..2871df203 100644
--- a/res/TensorFlowLiteRecipes/TransposeConv_001/test.recipe
+++ b/res/TensorFlowLiteRecipes/TransposeConv_001/test.recipe
@@ -35,6 +35,7 @@ operation {
padding: SAME
stride_w: 1
stride_h: 1
+ activation: NONE
}
input: "out_shape"
input: "ker"
diff --git a/res/TensorFlowLiteSchema/2.10.1/schema.fbs b/res/TensorFlowLiteSchema/2.10.1/schema.fbs
new file mode 100644
index 000000000..2c9b0a84d
--- /dev/null
+++ b/res/TensorFlowLiteSchema/2.10.1/schema.fbs
@@ -0,0 +1,1306 @@
+// Copyright 2017 The TensorFlow Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Revision History
+// Version 0: Initial version.
+// Version 1: Add subgraphs to schema.
+// Version 2: Rename operators to conform to NN API.
+// Version 3: Move buffer data from Model.Subgraph.Tensors to Model.Buffers.
+// Version 3a: Add new builtin op code field. Has backward compatibility with
+// version 3.
+// Version 3b: Rename fields in SignatureDef. Has backward compatibility with
+// version 3 and 3a.
+
+namespace tflite;
+
+// This corresponds to the version.
+file_identifier "TFL3";
+// File extension of any written files.
+file_extension "tflite";
+
+// IMPORTANT: All new members of tables, enums and unions must be added at the
+// end to ensure backwards compatibility.
+
+// The type of data stored in a tensor.
+enum TensorType : byte {
+ FLOAT32 = 0,
+ FLOAT16 = 1,
+ INT32 = 2,
+ UINT8 = 3,
+ INT64 = 4,
+ STRING = 5,
+ BOOL = 6,
+ INT16 = 7,
+ COMPLEX64 = 8,
+ INT8 = 9,
+ FLOAT64 = 10,
+ COMPLEX128 = 11,
+ UINT64 = 12,
+ // Experimental: Resource and variant types are experimental, that are subject
+ // to change. Do not implement custom kernels using resource & variant types
+ // now.
+ RESOURCE = 13,
+ VARIANT = 14,
+ UINT32 = 15,
+ UINT16 = 16
+}
+
+// Custom quantization parameters for experimenting with new quantization
+// techniques.
+table CustomQuantization {
+ custom:[ubyte] (force_align: 16);
+}
+
+// Represents a specific quantization technique's parameters.
+union QuantizationDetails {
+ CustomQuantization,
+}
+
+// Parameters for converting a quantized tensor back to float.
+table QuantizationParameters {
+ // These four parameters are the asymmetric linear quantization parameters.
+ // Given a quantized value q, the corresponding float value f should be:
+ // f = scale * (q - zero_point)
+ // For other quantization types, the QuantizationDetails below is used.
+ min:[float]; // For importing back into tensorflow.
+ max:[float]; // For importing back into tensorflow.
+ scale:[float]; // For dequantizing the tensor's values.
+ zero_point:[long];
+
+ // If this is not none, the other quantization parameters (i.e. min, max,
+ // scale, zero_point fields above) are ignored and the value of the
+ // QuantizationDetails union should be used.
+ details:QuantizationDetails;
+
+ // Specifies the dimension of the Tensor's shape that the scales and
+ // zero_points correspond to. For example, a tensor t, with dims=[4, 3, 2, 1]
+ // with quantization params:
+ // scale=[1.0, 2.0, 3.0], zero_point=[1, 2, 3], quantization_dimension=1
+ // will be quantized across the second dimension of t.
+ // t[:, 0, :, :] will have scale[0]=1.0, zero_point[0]=1
+ // t[:, 1, :, :] will have scale[1]=2.0, zero_point[0]=2
+ // t[:, 2, :, :] will have scale[2]=3.0, zero_point[0]=3
+ quantized_dimension:int;
+}
+
+// Sparse tensors.
+// We use a modification of the TACO format.
+// Reference: http://tensor-compiler.org/kjolstad-oopsla17-tensor-compiler.pdf
+//
+// To encode a conceptual n-dimensional dense tensor with dims (d0, ..., dn-1),
+// potentially with a k-dimensional block (0 <= k <= n) with dims
+// (dn, ..., dn+k-1), the format needs to specify:
+// 1. In what order to traverse these dimensions. For example, to store a 2-D
+// matrix in row major order, the traversal order would be (d0, d1),
+// whereas to store it in column major order, the traversal order would be
+// (d1, d0). If the 2-D matrix has a 2-D inner block, the traversal order
+// could be (d0, d1, d2, d3).
+// 2. How each block dimension in (dn, ..., dn+k-1) maps to the original
+// tensor dimension in (d0, ..., dn-1).
+// 3. In the traversal order defined above, the format (dense vs. sparse) and
+// index metadata for each dimension. For a dense dimension, this is just
+// the size of that dimension. For a sparse dimension, it's the same as
+// the compressed index defined in the Compressed Sparse Row (CSR) format.
+// (http://scipy-lectures.org/advanced/scipy_sparse/csr_matrix.html)
+
+// The storage type for a dimension. Currently we support:
+// 1. DENSE: each coordinate in this dimension is stored implicitly.
+// 2. SPARSE_CSR: only the coordinates with non-zero elements are stored. The
+// compression technique is the same what CSR uses.
+// More types like a sparse dimension with a different compression technique
+// could be added to the list in the future.
+enum DimensionType : byte {
+ DENSE = 0,
+ SPARSE_CSR = 1,
+}
+
+table Int32Vector {
+ values:[int];
+}
+
+table Uint16Vector {
+ values:[ushort] (force_align: 4);
+}
+
+table Uint8Vector {
+ values:[ubyte] (force_align: 4);
+}
+
+// Variable-typed buffer to store the index metadata for a sparse dimension.
+// The widest type is Int32 instead of UInt32 because tensor's shape is a int32
+// vector. We don't want the per-dimensional index to overflow that range.
+union SparseIndexVector {
+ Int32Vector,
+ Uint16Vector,
+ Uint8Vector
+}
+
+table DimensionMetadata {
+ // Whether a dimension is dense or sparse.
+ format:DimensionType;
+ // Index metadata used for a dimension.
+ // - If format is DimensionType.DENSE then we use the dense_size field to
+ // store the size of that dimension. Each index in that dimension is
+ // stored implicitly.
+ // - If format is DimensionType.SPARSE_CSR then we use array_segments and
+ // array_indices to encode that dimension. array_segments represents how
+ // to segment the indices array, each segment corresponds to one element
+ // in the previous dimension. array_indices represents the index of the
+ // non-zero elements within this dimension (as those in the CSR matrix
+ // format, where the first array is row pointers and the second array is
+ // column indices).
+ dense_size:int;
+ array_segments:SparseIndexVector;
+ array_indices:SparseIndexVector;
+}
+
+// Parameters to encode a sparse TfLite tensor.
+table SparsityParameters {
+ // The traversal order of the dimensions defined in the `shape` field of the
+ // conceptual dense tensor. For a n-dimensional tensors with dims (d0, d1,
+ // ..., dn-1),
+ // - if not block sparse, the traversal_order is just a permutation of (d0,
+ // ..., dn-1). For example, a 2-D matrix stored in row-major order would
+ // have traversal_order = (d0, d1).
+ // - if block sparse with a k-dimensional block (0 <= k <= n), the
+ // traversal_order has n + k elements. The first n elements are still a
+ // permutation of (d0, ..., dn-1). The lask k elements are a permutation
+ // of (dn, ..., dn+k-1), defining how to traverse a block internally. For
+ // example, a 2-D matrix with 2-D blocks, both stored in row-major order
+ // would have traversal_order = (d0, d1, d2, d3).
+ traversal_order:[int];
+ // For an n-dimensional tensor with a k-dimensional block (0 <= k <= n),
+ // stores how a block dimension in (dn, ..., dn+k-1) maps to the original
+ // tensor dimension in (d0, ..., dn).
+ // It's stored in the order of (dn, ..., dn+k-1).
+ // If not block-sparse, this field is NULL.
+ block_map:[int];
+ // In the traversal order defined above, the metadata needed for
+ // each dimension to locate the non-zero values in the original dense tensor.
+ // The size of the dim_metadata array = the size of the traversal_order array
+ // = n + k.
+ dim_metadata:[DimensionMetadata];
+}
+
+table Tensor {
+ // The tensor shape. The meaning of each entry is operator-specific but
+ // builtin ops use: [batch size, height, width, number of channels] (That's
+ // Tensorflow's NHWC).
+ shape:[int];
+ type:TensorType;
+ // An index that refers to the buffers table at the root of the model. Or,
+ // if there is no data buffer associated (i.e. intermediate results), then
+ // this is 0 (which refers to an always existent empty buffer).
+ //
+ // The data_buffer itself is an opaque container, with the assumption that the
+ // target device is little-endian. In addition, all builtin operators assume
+ // the memory is ordered such that if `shape` is [4, 3, 2], then index
+ // [i, j, k] maps to data_buffer[i*3*2 + j*2 + k].
+ buffer:uint;
+ name:string; // For debugging and importing back into tensorflow.
+ quantization:QuantizationParameters; // Optional.
+
+ is_variable:bool = false;
+
+ // Parameters to encode a sparse tensor. See the example in
+ // tensorflow/lite/testdata/sparse_tensor.json.
+ sparsity:SparsityParameters; // Optional.
+
+ // Encodes `shape` with unknown dimensions. Unknown dimensions are
+ // represented with -1.
+ shape_signature:[int]; // Optional.
+
+ // If false, the rank or the number of tensor dimensions is unknown.
+ // If false, "shape" must be [].
+ has_rank: bool = false;
+}
+
+// A list of builtin operators. Builtin operators are slightly faster than custom
+// ones, but not by much. Moreover, while custom operators accept an opaque
+// object containing configuration parameters, builtins have a predetermined
+// set of acceptable options.
+// LINT.IfChange
+enum BuiltinOperator : int32 {
+ ADD = 0,
+ AVERAGE_POOL_2D = 1,
+ CONCATENATION = 2,
+ CONV_2D = 3,
+ DEPTHWISE_CONV_2D = 4,
+ DEPTH_TO_SPACE = 5,
+ DEQUANTIZE = 6,
+ EMBEDDING_LOOKUP = 7,
+ FLOOR = 8,
+ FULLY_CONNECTED = 9,
+ HASHTABLE_LOOKUP = 10,
+ L2_NORMALIZATION = 11,
+ L2_POOL_2D = 12,
+ LOCAL_RESPONSE_NORMALIZATION = 13,
+ LOGISTIC = 14,
+ LSH_PROJECTION = 15,
+ LSTM = 16,
+ MAX_POOL_2D = 17,
+ MUL = 18,
+ RELU = 19,
+ // NOTE(aselle): RELU_N1_TO_1 used to be called RELU1, but it was renamed
+ // since different model developers use RELU1 in different ways. Never
+ // create another op called RELU1.
+ RELU_N1_TO_1 = 20,
+ RELU6 = 21,
+ RESHAPE = 22,
+ RESIZE_BILINEAR = 23,
+ RNN = 24,
+ SOFTMAX = 25,
+ SPACE_TO_DEPTH = 26,
+ SVDF = 27,
+ TANH = 28,
+ CONCAT_EMBEDDINGS = 29,
+ SKIP_GRAM = 30,
+ CALL = 31,
+ CUSTOM = 32,
+ EMBEDDING_LOOKUP_SPARSE = 33,
+ PAD = 34,
+ UNIDIRECTIONAL_SEQUENCE_RNN = 35,
+ GATHER = 36,
+ BATCH_TO_SPACE_ND = 37,
+ SPACE_TO_BATCH_ND = 38,
+ TRANSPOSE = 39,
+ MEAN = 40,
+ SUB = 41,
+ DIV = 42,
+ SQUEEZE = 43,
+ UNIDIRECTIONAL_SEQUENCE_LSTM = 44,
+ STRIDED_SLICE = 45,
+ BIDIRECTIONAL_SEQUENCE_RNN = 46,
+ EXP = 47,
+ TOPK_V2 = 48,
+ SPLIT = 49,
+ LOG_SOFTMAX = 50,
+ // DELEGATE is a special op type for the operations which are delegated to
+ // other backends.
+ // WARNING: Experimental interface, subject to change
+ DELEGATE = 51,
+ BIDIRECTIONAL_SEQUENCE_LSTM = 52,
+ CAST = 53,
+ PRELU = 54,
+ MAXIMUM = 55,
+ ARG_MAX = 56,
+ MINIMUM = 57,
+ LESS = 58,
+ NEG = 59,
+ PADV2 = 60,
+ GREATER = 61,
+ GREATER_EQUAL = 62,
+ LESS_EQUAL = 63,
+ SELECT = 64,
+ SLICE = 65,
+ SIN = 66,
+ TRANSPOSE_CONV = 67,
+ SPARSE_TO_DENSE = 68,
+ TILE = 69,
+ EXPAND_DIMS = 70,
+ EQUAL = 71,
+ NOT_EQUAL = 72,
+ LOG = 73,
+ SUM = 74,
+ SQRT = 75,
+ RSQRT = 76,
+ SHAPE = 77,
+ POW = 78,
+ ARG_MIN = 79,
+ FAKE_QUANT = 80,
+ REDUCE_PROD = 81,
+ REDUCE_MAX = 82,
+ PACK = 83,
+ LOGICAL_OR = 84,
+ ONE_HOT = 85,
+ LOGICAL_AND = 86,
+ LOGICAL_NOT = 87,
+ UNPACK = 88,
+ REDUCE_MIN = 89,
+ FLOOR_DIV = 90,
+ REDUCE_ANY = 91,
+ SQUARE = 92,
+ ZEROS_LIKE = 93,
+ FILL = 94,
+ FLOOR_MOD = 95,
+ RANGE = 96,
+ RESIZE_NEAREST_NEIGHBOR = 97,
+ LEAKY_RELU = 98,
+ SQUARED_DIFFERENCE = 99,
+ MIRROR_PAD = 100,
+ ABS = 101,
+ SPLIT_V = 102,
+ UNIQUE = 103,
+ CEIL = 104,
+ REVERSE_V2 = 105,
+ ADD_N = 106,
+ GATHER_ND = 107,
+ COS = 108,
+ WHERE = 109,
+ RANK = 110,
+ ELU = 111,
+ REVERSE_SEQUENCE = 112,
+ MATRIX_DIAG = 113,
+ QUANTIZE = 114,
+ MATRIX_SET_DIAG = 115,
+ ROUND = 116,
+ HARD_SWISH = 117,
+ IF = 118,
+ WHILE = 119,
+ NON_MAX_SUPPRESSION_V4 = 120,
+ NON_MAX_SUPPRESSION_V5 = 121,
+ SCATTER_ND = 122,
+ SELECT_V2 = 123,
+ DENSIFY = 124,
+ SEGMENT_SUM = 125,
+ BATCH_MATMUL = 126,
+ PLACEHOLDER_FOR_GREATER_OP_CODES = 127,
+ CUMSUM = 128,
+ CALL_ONCE = 129,
+ BROADCAST_TO = 130,
+ RFFT2D = 131,
+ CONV_3D = 132,
+ IMAG=133,
+ REAL=134,
+ COMPLEX_ABS=135,
+ HASHTABLE = 136,
+ HASHTABLE_FIND = 137,
+ HASHTABLE_IMPORT = 138,
+ HASHTABLE_SIZE = 139,
+ REDUCE_ALL = 140,
+ CONV_3D_TRANSPOSE = 141,
+ VAR_HANDLE = 142,
+ READ_VARIABLE = 143,
+ ASSIGN_VARIABLE = 144,
+ BROADCAST_ARGS = 145,
+ RANDOM_STANDARD_NORMAL = 146,
+ BUCKETIZE = 147,
+ RANDOM_UNIFORM = 148,
+ MULTINOMIAL = 149,
+ GELU = 150,
+ DYNAMIC_UPDATE_SLICE = 151,
+ RELU_0_TO_1 = 152,
+ UNSORTED_SEGMENT_PROD = 153,
+ UNSORTED_SEGMENT_MAX = 154,
+ UNSORTED_SEGMENT_SUM = 155,
+ ATAN2 = 156
+}
+// LINT.ThenChange(nnapi_linter/linter.proto)
+
+// Options for the builtin operators.
+union BuiltinOptions {
+ Conv2DOptions,
+ DepthwiseConv2DOptions,
+ ConcatEmbeddingsOptions,
+ LSHProjectionOptions,
+ Pool2DOptions,
+ SVDFOptions,
+ RNNOptions,
+ FullyConnectedOptions,
+ SoftmaxOptions,
+ ConcatenationOptions,
+ AddOptions,
+ L2NormOptions,
+ LocalResponseNormalizationOptions,
+ LSTMOptions,
+ ResizeBilinearOptions,
+ CallOptions,
+ ReshapeOptions,
+ SkipGramOptions,
+ SpaceToDepthOptions,
+ EmbeddingLookupSparseOptions,
+ MulOptions,
+ PadOptions,
+ GatherOptions,
+ BatchToSpaceNDOptions,
+ SpaceToBatchNDOptions,
+ TransposeOptions,
+ ReducerOptions,
+ SubOptions,
+ DivOptions,
+ SqueezeOptions,
+ SequenceRNNOptions,
+ StridedSliceOptions,
+ ExpOptions,
+ TopKV2Options,
+ SplitOptions,
+ LogSoftmaxOptions,
+ CastOptions,
+ DequantizeOptions,
+ MaximumMinimumOptions,
+ ArgMaxOptions,
+ LessOptions,
+ NegOptions,
+ PadV2Options,
+ GreaterOptions,
+ GreaterEqualOptions,
+ LessEqualOptions,
+ SelectOptions,
+ SliceOptions,
+ TransposeConvOptions,
+ SparseToDenseOptions,
+ TileOptions,
+ ExpandDimsOptions,
+ EqualOptions,
+ NotEqualOptions,
+ ShapeOptions,
+ PowOptions,
+ ArgMinOptions,
+ FakeQuantOptions,
+ PackOptions,
+ LogicalOrOptions,
+ OneHotOptions,
+ LogicalAndOptions,
+ LogicalNotOptions,
+ UnpackOptions,
+ FloorDivOptions,
+ SquareOptions,
+ ZerosLikeOptions,
+ FillOptions,
+ BidirectionalSequenceLSTMOptions,
+ BidirectionalSequenceRNNOptions,
+ UnidirectionalSequenceLSTMOptions,
+ FloorModOptions,
+ RangeOptions,
+ ResizeNearestNeighborOptions,
+ LeakyReluOptions,
+ SquaredDifferenceOptions,
+ MirrorPadOptions,
+ AbsOptions,
+ SplitVOptions,
+ UniqueOptions,
+ ReverseV2Options,
+ AddNOptions,
+ GatherNdOptions,
+ CosOptions,
+ WhereOptions,
+ RankOptions,
+ ReverseSequenceOptions,
+ MatrixDiagOptions,
+ QuantizeOptions,
+ MatrixSetDiagOptions,
+ HardSwishOptions,
+ IfOptions,
+ WhileOptions,
+ DepthToSpaceOptions,
+ NonMaxSuppressionV4Options,
+ NonMaxSuppressionV5Options,
+ ScatterNdOptions,
+ SelectV2Options,
+ DensifyOptions,
+ SegmentSumOptions,
+ BatchMatMulOptions,
+ CumsumOptions,
+ CallOnceOptions,
+ BroadcastToOptions,
+ Rfft2dOptions,
+ Conv3DOptions,
+ HashtableOptions,
+ HashtableFindOptions,
+ HashtableImportOptions,
+ HashtableSizeOptions,
+ VarHandleOptions,
+ ReadVariableOptions,
+ AssignVariableOptions,
+ RandomOptions,
+ BucketizeOptions,
+ GeluOptions,
+ DynamicUpdateSliceOptions,
+ UnsortedSegmentProdOptions,
+ UnsortedSegmentMaxOptions,
+ UnsortedSegmentSumOptions,
+ ATan2Options
+}
+
+// LINT.IfChange
+enum Padding : byte { SAME, VALID }
+// LINT.ThenChange(//tensorflow/compiler/mlir/lite/ir/tfl_op_enums.td)
+
+// LINT.IfChange
+enum ActivationFunctionType : byte {
+ NONE = 0,
+ RELU = 1,
+ RELU_N1_TO_1 = 2,
+ RELU6 = 3,
+ TANH = 4,
+ SIGN_BIT = 5,
+}
+// LINT.ThenChange(//tensorflow/compiler/mlir/lite/ir/tfl_op_enums.td)
+
+table Conv2DOptions {
+ padding:Padding;
+ stride_w:int;
+ stride_h:int;
+ fused_activation_function:ActivationFunctionType;
+ dilation_w_factor:int = 1;
+ dilation_h_factor:int = 1;
+}
+
+// Options for both Conv3D and Conv3DTranspose.
+table Conv3DOptions {
+ padding:Padding;
+ stride_d:int;
+ stride_w:int;
+ stride_h:int;
+ fused_activation_function:ActivationFunctionType;
+ dilation_d_factor:int = 1;
+ dilation_w_factor:int = 1;
+ dilation_h_factor:int = 1;
+}
+
+table Pool2DOptions {
+ padding:Padding;
+ stride_w:int;
+ stride_h:int;
+ filter_width:int;
+ filter_height:int;
+ fused_activation_function:ActivationFunctionType;
+}
+
+table DepthwiseConv2DOptions {
+ // Parameters for DepthwiseConv version 1 or above.
+ padding:Padding;
+ stride_w:int;
+ stride_h:int;
+ // `depth_multiplier` is redundant. It's used by CPU kernels in
+ // TensorFlow 2.0 or below, but ignored in versions above.
+ // See comments in lite/c/builtin_op_data.h for more details.
+ depth_multiplier:int;
+ fused_activation_function:ActivationFunctionType;
+ // Parameters for DepthwiseConv version 2 or above.
+ dilation_w_factor:int = 1;
+ dilation_h_factor:int = 1;
+}
+
+table ConcatEmbeddingsOptions {
+ num_channels:int;
+ num_columns_per_channel:[int];
+ embedding_dim_per_channel:[int]; // This could be inferred from parameters.
+}
+
+enum LSHProjectionType: byte {
+ UNKNOWN = 0,
+ SPARSE = 1,
+ DENSE = 2,
+}
+
+table LSHProjectionOptions {
+ type: LSHProjectionType;
+}
+
+table SVDFOptions {
+ rank:int;
+ fused_activation_function:ActivationFunctionType;
+ // For weights-only quantization, use asymmetric quantization for non
+ // constant inputs at evaluation time.
+ asymmetric_quantize_inputs:bool;
+}
+
+// An implementation of TensorFlow RNNCell.
+table RNNOptions {
+ fused_activation_function:ActivationFunctionType;
+ asymmetric_quantize_inputs:bool;
+}
+
+// An implementation of TensorFlow dynamic_rnn with RNNCell.
+table SequenceRNNOptions {
+ time_major:bool;
+ fused_activation_function:ActivationFunctionType;
+ asymmetric_quantize_inputs:bool;
+}
+
+// An implementation of TensorFlow bidrectional_dynamic_rnn with RNNCell.
+table BidirectionalSequenceRNNOptions {
+ time_major:bool;
+ fused_activation_function:ActivationFunctionType;
+ merge_outputs: bool;
+ asymmetric_quantize_inputs:bool;
+}
+
+// LINT.IfChange
+enum FullyConnectedOptionsWeightsFormat: byte {
+ DEFAULT = 0,
+ SHUFFLED4x16INT8 = 1,
+}
+// LINT.ThenChange(//tensorflow/compiler/mlir/lite/ir/tfl_op_enums.td)
+
+// An implementation of TensorFlow fully_connected (a.k.a Dense) layer.
+table FullyConnectedOptions {
+ // Parameters for FullyConnected version 1 or above.
+ fused_activation_function:ActivationFunctionType;
+
+ // Parameters for FullyConnected version 2 or above.
+ weights_format:FullyConnectedOptionsWeightsFormat = DEFAULT;
+
+ // Parameters for FullyConnected version 5 or above.
+ // If set to true, then the number of dimension is preserved. Furthermore,
+ // all but the last dimension of the input and output shapes will be equal.
+ keep_num_dims: bool;
+
+ // Parameters for FullyConnected version 7 or above.
+ // If set to true, then weights-only op will use asymmetric quantization for
+ // inputs.
+ asymmetric_quantize_inputs: bool;
+}
+
+table SoftmaxOptions {
+ beta: float;
+}
+
+// An implementation of TensorFlow concat.
+table ConcatenationOptions {
+ axis:int;
+ fused_activation_function:ActivationFunctionType;
+}
+
+table AddOptions {
+ fused_activation_function:ActivationFunctionType;
+ // Parameters supported by version 3.
+ pot_scale_int16:bool = true;
+}
+
+table MulOptions {
+ fused_activation_function:ActivationFunctionType;
+}
+
+table L2NormOptions {
+ // This field is currently ignored in the L2 Norm Op.
+ fused_activation_function:ActivationFunctionType;
+}
+
+table LocalResponseNormalizationOptions {
+ radius:int;
+ bias:float;
+ alpha:float;
+ beta:float;
+}
+
+// LINT.IfChange
+enum LSTMKernelType : byte {
+ // Full LSTM kernel which supports peephole and projection.
+ FULL = 0,
+ // Basic LSTM kernels. Equivalent to TensorFlow BasicLSTMCell.
+ BASIC = 1,
+}
+// LINT.ThenChange(//tensorflow/compiler/mlir/lite/ir/tfl_op_enums.td)
+
+// An implementation of TensorFlow LSTMCell and CoupledInputForgetGateLSTMCell
+table LSTMOptions {
+ // Parameters for LSTM version 1 or above.
+ fused_activation_function:ActivationFunctionType;
+ cell_clip: float; // Optional, 0.0 means no clipping
+ proj_clip: float; // Optional, 0.0 means no clipping
+
+ // Parameters for LSTM version 2 or above.
+ // Basic kernel is only supported in version 2 or above.
+ kernel_type: LSTMKernelType = FULL;
+
+ // Parameters for LSTM version 4 or above.
+ asymmetric_quantize_inputs: bool;
+}
+
+// An implementation of TensorFlow dynamic_rnn with LSTMCell.
+table UnidirectionalSequenceLSTMOptions {
+ fused_activation_function:ActivationFunctionType;
+ cell_clip: float; // Optional, 0.0 means no clipping
+ proj_clip: float; // Optional, 0.0 means no clipping
+
+ // If true then first dimension is sequence, otherwise batch.
+ time_major:bool;
+
+ // Parameter for Unidirectional Sequence LSTM version 4.
+ asymmetric_quantize_inputs:bool;
+}
+
+table BidirectionalSequenceLSTMOptions {
+ // Parameters supported by version 1:
+ fused_activation_function:ActivationFunctionType;
+ cell_clip: float; // Optional, 0.0 means no clipping
+ proj_clip: float; // Optional, 0.0 means no clipping
+
+ // If true, store the outputs of both directions into the first output.
+ merge_outputs: bool;
+
+ // Parameters supported by version 2:
+ // If true then first dimension is sequence, otherwise batch.
+ // Version 1 implementations assumed time_major to be true, so this default
+ // value should never change.
+ time_major: bool = true;
+
+ // Parameters for version 3 or above.
+ asymmetric_quantize_inputs:bool;
+}
+
+table ResizeBilinearOptions {
+ new_height: int (deprecated);
+ new_width: int (deprecated);
+ align_corners: bool;
+ half_pixel_centers: bool;
+}
+
+table ResizeNearestNeighborOptions {
+ align_corners: bool;
+ half_pixel_centers: bool;
+}
+
+// A call operation options
+table CallOptions {
+ // The subgraph index that needs to be called.
+ subgraph:uint;
+}
+
+table PadOptions {
+}
+
+table PadV2Options {
+}
+
+table ReshapeOptions {
+ new_shape:[int];
+}
+
+table SpaceToBatchNDOptions {
+}
+
+table BatchToSpaceNDOptions {
+}
+
+table SkipGramOptions {
+ ngram_size: int;
+ max_skip_size: int;
+ include_all_ngrams: bool;
+}
+
+table SpaceToDepthOptions {
+ block_size: int;
+}
+
+table DepthToSpaceOptions {
+ block_size: int;
+}
+
+table SubOptions {
+ fused_activation_function:ActivationFunctionType;
+ // Parameters supported by version 5
+ pot_scale_int16:bool = true;
+}
+
+table DivOptions {
+ fused_activation_function:ActivationFunctionType;
+}
+
+table TopKV2Options {
+}
+
+enum CombinerType : byte {
+ SUM = 0,
+ MEAN = 1,
+ SQRTN = 2,
+}
+
+table EmbeddingLookupSparseOptions {
+ combiner:CombinerType;
+}
+
+table GatherOptions {
+ axis: int;
+ // Parameters for Gather version 5 or above.
+ batch_dims: int = 0;
+}
+
+table TransposeOptions {
+}
+
+table ExpOptions {
+}
+
+table CosOptions {
+}
+
+table ReducerOptions {
+ keep_dims: bool;
+}
+
+table SqueezeOptions {
+ squeeze_dims:[int];
+}
+
+table SplitOptions {
+ num_splits: int;
+}
+
+table SplitVOptions {
+ num_splits: int;
+}
+
+table StridedSliceOptions {
+ begin_mask: int;
+ end_mask: int;
+ ellipsis_mask: int;
+ new_axis_mask: int;
+ shrink_axis_mask: int;
+}
+
+table LogSoftmaxOptions {
+}
+
+table CastOptions {
+ in_data_type: TensorType;
+ out_data_type: TensorType;
+}
+
+table DequantizeOptions {
+}
+
+table MaximumMinimumOptions {
+}
+
+table TileOptions {
+}
+
+table ArgMaxOptions {
+ output_type : TensorType;
+}
+
+table ArgMinOptions {
+ output_type : TensorType;
+}
+
+table GreaterOptions {
+}
+
+table GreaterEqualOptions {
+}
+
+table LessOptions {
+}
+
+table LessEqualOptions {
+}
+
+table NegOptions {
+}
+
+table SelectOptions {
+}
+
+table SliceOptions {
+}
+
+table TransposeConvOptions {
+ padding:Padding;
+ stride_w:int;
+ stride_h:int;
+}
+
+table ExpandDimsOptions {
+}
+
+table SparseToDenseOptions {
+ validate_indices:bool;
+}
+
+table EqualOptions {
+}
+
+table NotEqualOptions {
+}
+
+table ShapeOptions {
+ // Optional output type of the operation (int32 or int64). Defaults to int32.
+ out_type : TensorType;
+}
+
+table RankOptions {
+}
+
+table PowOptions {
+}
+
+table FakeQuantOptions {
+ // Parameters supported by version 1:
+ min:float;
+ max:float;
+ num_bits:int;
+
+ // Parameters supported by version 2:
+ narrow_range:bool;
+}
+
+table PackOptions {
+ values_count:int;
+ axis:int;
+}
+
+table LogicalOrOptions {
+}
+
+table OneHotOptions {
+ axis:int;
+}
+
+table AbsOptions {
+}
+
+
+table HardSwishOptions {
+}
+
+table LogicalAndOptions {
+}
+
+table LogicalNotOptions {
+}
+
+table UnpackOptions {
+ num:int;
+ axis:int;
+}
+
+table FloorDivOptions {
+}
+
+table SquareOptions {
+}
+
+table ZerosLikeOptions {
+}
+
+table FillOptions {
+}
+
+table FloorModOptions {
+}
+
+table RangeOptions {
+}
+
+table LeakyReluOptions {
+ alpha:float;
+}
+
+table SquaredDifferenceOptions {
+}
+
+// LINT.IfChange
+enum MirrorPadMode : byte {
+ // Doesn't include borders.
+ REFLECT = 0,
+ // Includes borders.
+ SYMMETRIC = 1,
+}
+// LINT.ThenChange(//tensorflow/compiler/mlir/lite/ir/tfl_op_enums.td)
+
+table MirrorPadOptions {
+ mode:MirrorPadMode;
+}
+
+table UniqueOptions {
+ idx_out_type:TensorType = INT32;
+}
+
+table ReverseV2Options {
+}
+
+table AddNOptions {
+}
+
+table GatherNdOptions {
+}
+
+table WhereOptions {
+}
+
+table ReverseSequenceOptions {
+ seq_dim:int;
+ batch_dim:int = 0;
+}
+
+table MatrixDiagOptions {
+}
+
+table QuantizeOptions {
+}
+
+table MatrixSetDiagOptions {
+}
+
+table IfOptions {
+ then_subgraph_index:int;
+ else_subgraph_index:int;
+}
+
+table CallOnceOptions {
+ init_subgraph_index:int;
+}
+
+table WhileOptions {
+ cond_subgraph_index:int;
+ body_subgraph_index:int;
+}
+
+table NonMaxSuppressionV4Options {
+}
+
+table NonMaxSuppressionV5Options {
+}
+
+table ScatterNdOptions {
+}
+
+table SelectV2Options {
+}
+
+table DensifyOptions {
+}
+
+table SegmentSumOptions {
+}
+
+table BatchMatMulOptions {
+ adj_x:bool;
+ adj_y:bool;
+ // Parameters for BatchMatMul version 4 or above.
+ // If set to true, then weights-only op will use asymmetric quantization for
+ // inputs.
+ asymmetric_quantize_inputs: bool;
+}
+
+table CumsumOptions {
+ exclusive:bool;
+ reverse:bool;
+}
+
+table BroadcastToOptions {
+}
+
+table Rfft2dOptions {
+}
+
+table HashtableOptions {
+ // The identity of hash tables. This identity will be used across different
+ // subgraphs in the same interpreter instance.
+ table_id:int;
+ key_dtype:TensorType;
+ value_dtype:TensorType;
+}
+
+table HashtableFindOptions {
+}
+
+table HashtableImportOptions {
+}
+
+table HashtableSizeOptions {
+}
+
+table VarHandleOptions {
+ container:string;
+ shared_name:string;
+}
+
+table ReadVariableOptions {
+}
+
+table AssignVariableOptions {
+}
+
+table RandomOptions {
+ seed: long;
+ seed2: long;
+}
+
+table BucketizeOptions {
+ boundaries: [float]; // The bucket boundaries.
+}
+
+table GeluOptions {
+ approximate: bool;
+}
+
+table DynamicUpdateSliceOptions {
+}
+
+table UnsortedSegmentProdOptions {
+}
+
+table UnsortedSegmentMaxOptions {
+}
+
+table UnsortedSegmentSumOptions {
+}
+
+table ATan2Options {
+}
+
+
+// An OperatorCode can be an enum value (BuiltinOperator) if the operator is a
+// builtin, or a string if the operator is custom.
+table OperatorCode {
+ // This field is for backward compatibility. This field will be used when
+ // the value of the extended builtin_code field has less than
+ // BulitinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES.
+ deprecated_builtin_code:byte;
+ custom_code:string;
+
+ // The version of the operator. The version need to be bumped whenever new
+ // parameters are introduced into an op.
+ version:int = 1;
+
+ // This field is introduced for resolving op builtin code shortage problem
+ // (the original BuiltinOperator enum field was represented as a byte).
+ // This field will be used when the value of the extended builtin_code field
+ // has greater than BulitinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES.
+ builtin_code:BuiltinOperator;
+}
+
+enum CustomOptionsFormat : byte {
+ FLEXBUFFERS = 0,
+}
+
+// An operator takes tensors as inputs and outputs. The type of operation being
+// performed is determined by an index into the list of valid OperatorCodes,
+// while the specifics of each operations is configured using builtin_options
+// or custom_options.
+table Operator {
+ // Index into the operator_codes array. Using an integer here avoids
+ // complicate map lookups.
+ opcode_index:uint;
+
+ // Optional input are indicated by -1.
+ inputs:[int];
+ outputs:[int];
+
+ builtin_options:BuiltinOptions;
+ custom_options:[ubyte];
+ custom_options_format:CustomOptionsFormat;
+
+ // A list of booleans indicating the input tensors which are being mutated by
+ // this operator.(e.g. used by RNN and LSTM).
+ // For example, if the "inputs" array refers to 5 tensors and the second and
+ // fifth are mutable variables, then this list will contain
+ // [false, true, false, false, true].
+ //
+ // If the list is empty, no variable is mutated in this operator.
+ // The list either has the same length as `inputs`, or is empty.
+ mutating_variable_inputs:[bool];
+
+ // A list of indices to the subgraph's "tensors" that are internal to an Op.
+ // Internal tensors are those that do not flow in or out of the operation,
+ // but instead are part of internal computation. As such, the operation's
+ // implementation may manage its memory more efficiently. They are needed
+ // however (i.e. not just an implementation detail) since they are part of the
+ // computation, which may require relevant metadata such as quantization
+ // parameters.
+ intermediates:[int];
+}
+
+// The root type, defining a subgraph, which typically represents an entire
+// model.
+table SubGraph {
+ // A list of all tensors used in this subgraph.
+ tensors:[Tensor];
+
+ // Indices of the tensors that are inputs into this subgraph. Note this is
+ // the list of non-static tensors that feed into the subgraph for inference.
+ inputs:[int];
+
+ // Indices of the tensors that are outputs out of this subgraph. Note this is
+ // the list of output tensors that are considered the product of the
+ // subgraph's inference.
+ outputs:[int];
+
+ // All operators, in execution order.
+ operators:[Operator];
+
+ // Name of this subgraph (used for debugging).
+ name:string;
+}
+
+// Table of raw data buffers (used for constant tensors). Referenced by tensors
+// by index. The generous alignment accommodates mmap-friendly data structures.
+table Buffer {
+ data:[ubyte] (force_align: 16);
+}
+
+table Metadata {
+ // A human readable string to uniquely identify a Metadata.
+ name:string;
+ // An index to the buffers table.
+ buffer:uint;
+}
+
+// Map from an alias name of tensor to tensor index in the graph.
+// This is used in Signature def.
+table TensorMap {
+ // Represents the alias to use for this tensor.
+ name:string;
+
+ // The actual tensor index in the primary graph, that 'name' corresponds to.
+ tensor_index:uint;
+}
+
+// This corresponds to SignatureDef in Tensorflow SavedModel.
+// The SignatureDef will be part of the SavedModel provided for conversion.
+table SignatureDef {
+ // Named inputs for this signature.
+ inputs:[TensorMap];
+
+ // Named outputs for this signature.
+ outputs:[TensorMap];
+
+ // Key value which was in the Tensorflow SavedModel SignatureDef map.
+ signature_key:string;
+
+ // Model tag, deprecated.
+ deprecated_tag:string (deprecated);
+
+ // Index of subgraphs that corresponds to the exported method.
+ subgraph_index:uint;
+}
+
+table Model {
+ // Version of the schema.
+ version:uint;
+
+ // A list of all operator codes used in this model. This is
+ // kept in order because operators carry an index into this
+ // vector.
+ operator_codes:[OperatorCode];
+
+ // All the subgraphs of the model. The 0th is assumed to be the main
+ // model.
+ subgraphs:[SubGraph];
+
+ // A description of the model.
+ description:string;
+
+ // Buffers of the model.
+ // Note the 0th entry of this array must be an empty buffer (sentinel).
+ // This is a convention so that tensors without a buffer can provide 0 as
+ // their buffer.
+ buffers:[Buffer];
+
+ // Metadata about the model. Indirects into the existings buffers list.
+ // Deprecated, prefer to use metadata field.
+ metadata_buffer:[int];
+
+ // Metadata about the model.
+ metadata:[Metadata];
+
+ // Optional SignatureDefs for the model.
+ signature_defs:[SignatureDef];
+}
+
+root_type Model;
diff --git a/res/TensorFlowLiteSchema/2.12.1/schema.fbs b/res/TensorFlowLiteSchema/2.12.1/schema.fbs
new file mode 100644
index 000000000..05a906db0
--- /dev/null
+++ b/res/TensorFlowLiteSchema/2.12.1/schema.fbs
@@ -0,0 +1,1340 @@
+// Copyright 2017 The TensorFlow Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Revision History
+// Version 0: Initial version.
+// Version 1: Add subgraphs to schema.
+// Version 2: Rename operators to conform to NN API.
+// Version 3: Move buffer data from Model.Subgraph.Tensors to Model.Buffers.
+// Version 3a: Add new builtin op code field. Has backward compatibility with
+// version 3.
+// Version 3b: Rename fields in SignatureDef. Has backward compatibility with
+// version 3 and 3a.
+
+namespace tflite;
+
+// This corresponds to the version.
+file_identifier "TFL3";
+// File extension of any written files.
+file_extension "tflite";
+
+// IMPORTANT: All new members of tables, enums and unions must be added at the
+// end to ensure backwards compatibility.
+
+// The type of data stored in a tensor.
+enum TensorType : byte {
+ FLOAT32 = 0,
+ FLOAT16 = 1,
+ INT32 = 2,
+ UINT8 = 3,
+ INT64 = 4,
+ STRING = 5,
+ BOOL = 6,
+ INT16 = 7,
+ COMPLEX64 = 8,
+ INT8 = 9,
+ FLOAT64 = 10,
+ COMPLEX128 = 11,
+ UINT64 = 12,
+ // Experimental: Resource and variant types are experimental, that are subject
+ // to change. Do not implement custom kernels using resource & variant types
+ // now.
+ RESOURCE = 13,
+ VARIANT = 14,
+ UINT32 = 15,
+ UINT16 = 16,
+ INT4 = 17,
+}
+
+// Custom quantization parameters for experimenting with new quantization
+// techniques.
+table CustomQuantization {
+ custom:[ubyte] (force_align: 16);
+}
+
+// Represents a specific quantization technique's parameters.
+union QuantizationDetails {
+ CustomQuantization,
+}
+
+// Parameters for converting a quantized tensor back to float.
+table QuantizationParameters {
+ // These four parameters are the asymmetric linear quantization parameters.
+ // Given a quantized value q, the corresponding float value f should be:
+ // f = scale * (q - zero_point)
+ // For other quantization types, the QuantizationDetails below is used.
+ min:[float]; // For importing back into tensorflow.
+ max:[float]; // For importing back into tensorflow.
+ scale:[float]; // For dequantizing the tensor's values.
+ zero_point:[long];
+
+ // If this is not none, the other quantization parameters (i.e. min, max,
+ // scale, zero_point fields above) are ignored and the value of the
+ // QuantizationDetails union should be used.
+ details:QuantizationDetails;
+
+ // Specifies the dimension of the Tensor's shape that the scales and
+ // zero_points correspond to. For example, a tensor t, with dims=[4, 3, 2, 1]
+ // with quantization params:
+ // scale=[1.0, 2.0, 3.0], zero_point=[1, 2, 3], quantization_dimension=1
+ // will be quantized across the second dimension of t.
+ // t[:, 0, :, :] will have scale[0]=1.0, zero_point[0]=1
+ // t[:, 1, :, :] will have scale[1]=2.0, zero_point[0]=2
+ // t[:, 2, :, :] will have scale[2]=3.0, zero_point[0]=3
+ quantized_dimension:int;
+}
+
+// Sparse tensors.
+// We use a modification of the TACO format.
+// Reference: http://tensor-compiler.org/kjolstad-oopsla17-tensor-compiler.pdf
+//
+// To encode a conceptual n-dimensional dense tensor with dims (d0, ..., dn-1),
+// potentially with a k-dimensional block (0 <= k <= n) with dims
+// (dn, ..., dn+k-1), the format needs to specify:
+// 1. In what order to traverse these dimensions. For example, to store a 2-D
+// matrix in row major order, the traversal order would be (d0, d1),
+// whereas to store it in column major order, the traversal order would be
+// (d1, d0). If the 2-D matrix has a 2-D inner block, the traversal order
+// could be (d0, d1, d2, d3).
+// 2. How each block dimension in (dn, ..., dn+k-1) maps to the original
+// tensor dimension in (d0, ..., dn-1).
+// 3. In the traversal order defined above, the format (dense vs. sparse) and
+// index metadata for each dimension. For a dense dimension, this is just
+// the size of that dimension. For a sparse dimension, it's the same as
+// the compressed index defined in the Compressed Sparse Row (CSR) format.
+// (http://scipy-lectures.org/advanced/scipy_sparse/csr_matrix.html)
+
+// The storage type for a dimension. Currently we support:
+// 1. DENSE: each coordinate in this dimension is stored implicitly.
+// 2. SPARSE_CSR: only the coordinates with non-zero elements are stored. The
+// compression technique is the same what CSR uses.
+// More types like a sparse dimension with a different compression technique
+// could be added to the list in the future.
+enum DimensionType : byte {
+ DENSE = 0,
+ SPARSE_CSR = 1,
+}
+
+table Int32Vector {
+ values:[int];
+}
+
+table Uint16Vector {
+ values:[ushort] (force_align: 4);
+}
+
+table Uint8Vector {
+ values:[ubyte] (force_align: 4);
+}
+
+// Variable-typed buffer to store the index metadata for a sparse dimension.
+// The widest type is Int32 instead of UInt32 because tensor's shape is a int32
+// vector. We don't want the per-dimensional index to overflow that range.
+union SparseIndexVector {
+ Int32Vector,
+ Uint16Vector,
+ Uint8Vector
+}
+
+table DimensionMetadata {
+ // Whether a dimension is dense or sparse.
+ format:DimensionType;
+ // Index metadata used for a dimension.
+ // - If format is DimensionType.DENSE then we use the dense_size field to
+ // store the size of that dimension. Each index in that dimension is
+ // stored implicitly.
+ // - If format is DimensionType.SPARSE_CSR then we use array_segments and
+ // array_indices to encode that dimension. array_segments represents how
+ // to segment the indices array, each segment corresponds to one element
+ // in the previous dimension. array_indices represents the index of the
+ // non-zero elements within this dimension (as those in the CSR matrix
+ // format, where the first array is row pointers and the second array is
+ // column indices).
+ dense_size:int;
+ array_segments:SparseIndexVector;
+ array_indices:SparseIndexVector;
+}
+
+// Parameters to encode a sparse TfLite tensor.
+table SparsityParameters {
+ // The traversal order of the dimensions defined in the `shape` field of the
+ // conceptual dense tensor. For a n-dimensional tensors with dims (d0, d1,
+ // ..., dn-1),
+ // - if not block sparse, the traversal_order is just a permutation of (d0,
+ // ..., dn-1). For example, a 2-D matrix stored in row-major order would
+ // have traversal_order = (d0, d1).
+ // - if block sparse with a k-dimensional block (0 <= k <= n), the
+ // traversal_order has n + k elements. The first n elements are still a
+ // permutation of (d0, ..., dn-1). The lask k elements are a permutation
+ // of (dn, ..., dn+k-1), defining how to traverse a block internally. For
+ // example, a 2-D matrix with 2-D blocks, both stored in row-major order
+ // would have traversal_order = (d0, d1, d2, d3).
+ traversal_order:[int];
+ // For an n-dimensional tensor with a k-dimensional block (0 <= k <= n),
+ // stores how a block dimension in (dn, ..., dn+k-1) maps to the original
+ // tensor dimension in (d0, ..., dn).
+ // It's stored in the order of (dn, ..., dn+k-1).
+ // If not block-sparse, this field is NULL.
+ block_map:[int];
+ // In the traversal order defined above, the metadata needed for
+ // each dimension to locate the non-zero values in the original dense tensor.
+ // The size of the dim_metadata array = the size of the traversal_order array
+ // = n + k.
+ dim_metadata:[DimensionMetadata];
+}
+
+// The nested tensor type for VARIANT type.
+table VariantSubType {
+ // The tensor shape.
+ shape:[int];
+ type:TensorType;
+ // If false, the rank or the number of tensor dimensions is unknown.
+ // If false, "shape" must be [].
+ has_rank: bool = false;
+}
+
+table Tensor {
+ // The tensor shape. The meaning of each entry is operator-specific but
+ // builtin ops use: [batch size, height, width, number of channels] (That's
+ // Tensorflow's NHWC).
+ shape:[int];
+ type:TensorType;
+ // An index that refers to the buffers table at the root of the model. Or,
+ // if there is no data buffer associated (i.e. intermediate results), then
+ // this is 0 (which refers to an always existent empty buffer).
+ //
+ // The data_buffer itself is an opaque container, with the assumption that the
+ // target device is little-endian. In addition, all builtin operators assume
+ // the memory is ordered such that if `shape` is [4, 3, 2], then index
+ // [i, j, k] maps to data_buffer[i*3*2 + j*2 + k].
+ buffer:uint;
+ name:string; // For debugging and importing back into tensorflow.
+ quantization:QuantizationParameters; // Optional.
+
+ is_variable:bool = false;
+
+ // Parameters to encode a sparse tensor. See the example in
+ // tensorflow/lite/testdata/sparse_tensor.json.
+ sparsity:SparsityParameters; // Optional.
+
+ // Encodes `shape` with unknown dimensions. Unknown dimensions are
+ // represented with -1.
+ shape_signature:[int]; // Optional.
+
+ // If false, the rank or the number of tensor dimensions is unknown.
+ // If false, "shape" must be [].
+ has_rank: bool = false;
+
+ // The nested Tensor types for VARIANT type. This is always empty for
+ // non-VARIANT types. This is optional because the nested type can be omitted.
+ // Currently only 1 subtype is supported. The field is defined as an array for
+ // flexibility of supporting multiple subtypes in the future.
+ variant_tensors:[VariantSubType];
+}
+
+// A list of builtin operators. Builtin operators are slightly faster than custom
+// ones, but not by much. Moreover, while custom operators accept an opaque
+// object containing configuration parameters, builtins have a predetermined
+// set of acceptable options.
+// LINT.IfChange
+enum BuiltinOperator : int32 {
+ ADD = 0,
+ AVERAGE_POOL_2D = 1,
+ CONCATENATION = 2,
+ CONV_2D = 3,
+ DEPTHWISE_CONV_2D = 4,
+ DEPTH_TO_SPACE = 5,
+ DEQUANTIZE = 6,
+ EMBEDDING_LOOKUP = 7,
+ FLOOR = 8,
+ FULLY_CONNECTED = 9,
+ HASHTABLE_LOOKUP = 10,
+ L2_NORMALIZATION = 11,
+ L2_POOL_2D = 12,
+ LOCAL_RESPONSE_NORMALIZATION = 13,
+ LOGISTIC = 14,
+ LSH_PROJECTION = 15,
+ LSTM = 16,
+ MAX_POOL_2D = 17,
+ MUL = 18,
+ RELU = 19,
+ // NOTE(aselle): RELU_N1_TO_1 used to be called RELU1, but it was renamed
+ // since different model developers use RELU1 in different ways. Never
+ // create another op called RELU1.
+ RELU_N1_TO_1 = 20,
+ RELU6 = 21,
+ RESHAPE = 22,
+ RESIZE_BILINEAR = 23,
+ RNN = 24,
+ SOFTMAX = 25,
+ SPACE_TO_DEPTH = 26,
+ SVDF = 27,
+ TANH = 28,
+ CONCAT_EMBEDDINGS = 29,
+ SKIP_GRAM = 30,
+ CALL = 31,
+ CUSTOM = 32,
+ EMBEDDING_LOOKUP_SPARSE = 33,
+ PAD = 34,
+ UNIDIRECTIONAL_SEQUENCE_RNN = 35,
+ GATHER = 36,
+ BATCH_TO_SPACE_ND = 37,
+ SPACE_TO_BATCH_ND = 38,
+ TRANSPOSE = 39,
+ MEAN = 40,
+ SUB = 41,
+ DIV = 42,
+ SQUEEZE = 43,
+ UNIDIRECTIONAL_SEQUENCE_LSTM = 44,
+ STRIDED_SLICE = 45,
+ BIDIRECTIONAL_SEQUENCE_RNN = 46,
+ EXP = 47,
+ TOPK_V2 = 48,
+ SPLIT = 49,
+ LOG_SOFTMAX = 50,
+ // DELEGATE is a special op type for the operations which are delegated to
+ // other backends.
+ // WARNING: Experimental interface, subject to change
+ DELEGATE = 51,
+ BIDIRECTIONAL_SEQUENCE_LSTM = 52,
+ CAST = 53,
+ PRELU = 54,
+ MAXIMUM = 55,
+ ARG_MAX = 56,
+ MINIMUM = 57,
+ LESS = 58,
+ NEG = 59,
+ PADV2 = 60,
+ GREATER = 61,
+ GREATER_EQUAL = 62,
+ LESS_EQUAL = 63,
+ SELECT = 64,
+ SLICE = 65,
+ SIN = 66,
+ TRANSPOSE_CONV = 67,
+ SPARSE_TO_DENSE = 68,
+ TILE = 69,
+ EXPAND_DIMS = 70,
+ EQUAL = 71,
+ NOT_EQUAL = 72,
+ LOG = 73,
+ SUM = 74,
+ SQRT = 75,
+ RSQRT = 76,
+ SHAPE = 77,
+ POW = 78,
+ ARG_MIN = 79,
+ FAKE_QUANT = 80,
+ REDUCE_PROD = 81,
+ REDUCE_MAX = 82,
+ PACK = 83,
+ LOGICAL_OR = 84,
+ ONE_HOT = 85,
+ LOGICAL_AND = 86,
+ LOGICAL_NOT = 87,
+ UNPACK = 88,
+ REDUCE_MIN = 89,
+ FLOOR_DIV = 90,
+ REDUCE_ANY = 91,
+ SQUARE = 92,
+ ZEROS_LIKE = 93,
+ FILL = 94,
+ FLOOR_MOD = 95,
+ RANGE = 96,
+ RESIZE_NEAREST_NEIGHBOR = 97,
+ LEAKY_RELU = 98,
+ SQUARED_DIFFERENCE = 99,
+ MIRROR_PAD = 100,
+ ABS = 101,
+ SPLIT_V = 102,
+ UNIQUE = 103,
+ CEIL = 104,
+ REVERSE_V2 = 105,
+ ADD_N = 106,
+ GATHER_ND = 107,
+ COS = 108,
+ WHERE = 109,
+ RANK = 110,
+ ELU = 111,
+ REVERSE_SEQUENCE = 112,
+ MATRIX_DIAG = 113,
+ QUANTIZE = 114,
+ MATRIX_SET_DIAG = 115,
+ ROUND = 116,
+ HARD_SWISH = 117,
+ IF = 118,
+ WHILE = 119,
+ NON_MAX_SUPPRESSION_V4 = 120,
+ NON_MAX_SUPPRESSION_V5 = 121,
+ SCATTER_ND = 122,
+ SELECT_V2 = 123,
+ DENSIFY = 124,
+ SEGMENT_SUM = 125,
+ BATCH_MATMUL = 126,
+ PLACEHOLDER_FOR_GREATER_OP_CODES = 127,
+ CUMSUM = 128,
+ CALL_ONCE = 129,
+ BROADCAST_TO = 130,
+ RFFT2D = 131,
+ CONV_3D = 132,
+ IMAG=133,
+ REAL=134,
+ COMPLEX_ABS=135,
+ HASHTABLE = 136,
+ HASHTABLE_FIND = 137,
+ HASHTABLE_IMPORT = 138,
+ HASHTABLE_SIZE = 139,
+ REDUCE_ALL = 140,
+ CONV_3D_TRANSPOSE = 141,
+ VAR_HANDLE = 142,
+ READ_VARIABLE = 143,
+ ASSIGN_VARIABLE = 144,
+ BROADCAST_ARGS = 145,
+ RANDOM_STANDARD_NORMAL = 146,
+ BUCKETIZE = 147,
+ RANDOM_UNIFORM = 148,
+ MULTINOMIAL = 149,
+ GELU = 150,
+ DYNAMIC_UPDATE_SLICE = 151,
+ RELU_0_TO_1 = 152,
+ UNSORTED_SEGMENT_PROD = 153,
+ UNSORTED_SEGMENT_MAX = 154,
+ UNSORTED_SEGMENT_SUM = 155,
+ ATAN2 = 156,
+ UNSORTED_SEGMENT_MIN = 157,
+ SIGN = 158
+}
+// LINT.ThenChange(nnapi_linter/linter.proto)
+
+// Options for the builtin operators.
+union BuiltinOptions {
+ Conv2DOptions,
+ DepthwiseConv2DOptions,
+ ConcatEmbeddingsOptions,
+ LSHProjectionOptions,
+ Pool2DOptions,
+ SVDFOptions,
+ RNNOptions,
+ FullyConnectedOptions,
+ SoftmaxOptions,
+ ConcatenationOptions,
+ AddOptions,
+ L2NormOptions,
+ LocalResponseNormalizationOptions,
+ LSTMOptions,
+ ResizeBilinearOptions,
+ CallOptions,
+ ReshapeOptions,
+ SkipGramOptions,
+ SpaceToDepthOptions,
+ EmbeddingLookupSparseOptions,
+ MulOptions,
+ PadOptions,
+ GatherOptions,
+ BatchToSpaceNDOptions,
+ SpaceToBatchNDOptions,
+ TransposeOptions,
+ ReducerOptions,
+ SubOptions,
+ DivOptions,
+ SqueezeOptions,
+ SequenceRNNOptions,
+ StridedSliceOptions,
+ ExpOptions,
+ TopKV2Options,
+ SplitOptions,
+ LogSoftmaxOptions,
+ CastOptions,
+ DequantizeOptions,
+ MaximumMinimumOptions,
+ ArgMaxOptions,
+ LessOptions,
+ NegOptions,
+ PadV2Options,
+ GreaterOptions,
+ GreaterEqualOptions,
+ LessEqualOptions,
+ SelectOptions,
+ SliceOptions,
+ TransposeConvOptions,
+ SparseToDenseOptions,
+ TileOptions,
+ ExpandDimsOptions,
+ EqualOptions,
+ NotEqualOptions,
+ ShapeOptions,
+ PowOptions,
+ ArgMinOptions,
+ FakeQuantOptions,
+ PackOptions,
+ LogicalOrOptions,
+ OneHotOptions,
+ LogicalAndOptions,
+ LogicalNotOptions,
+ UnpackOptions,
+ FloorDivOptions,
+ SquareOptions,
+ ZerosLikeOptions,
+ FillOptions,
+ BidirectionalSequenceLSTMOptions,
+ BidirectionalSequenceRNNOptions,
+ UnidirectionalSequenceLSTMOptions,
+ FloorModOptions,
+ RangeOptions,
+ ResizeNearestNeighborOptions,
+ LeakyReluOptions,
+ SquaredDifferenceOptions,
+ MirrorPadOptions,
+ AbsOptions,
+ SplitVOptions,
+ UniqueOptions,
+ ReverseV2Options,
+ AddNOptions,
+ GatherNdOptions,
+ CosOptions,
+ WhereOptions,
+ RankOptions,
+ ReverseSequenceOptions,
+ MatrixDiagOptions,
+ QuantizeOptions,
+ MatrixSetDiagOptions,
+ HardSwishOptions,
+ IfOptions,
+ WhileOptions,
+ DepthToSpaceOptions,
+ NonMaxSuppressionV4Options,
+ NonMaxSuppressionV5Options,
+ ScatterNdOptions,
+ SelectV2Options,
+ DensifyOptions,
+ SegmentSumOptions,
+ BatchMatMulOptions,
+ CumsumOptions,
+ CallOnceOptions,
+ BroadcastToOptions,
+ Rfft2dOptions,
+ Conv3DOptions,
+ HashtableOptions,
+ HashtableFindOptions,
+ HashtableImportOptions,
+ HashtableSizeOptions,
+ VarHandleOptions,
+ ReadVariableOptions,
+ AssignVariableOptions,
+ RandomOptions,
+ BucketizeOptions,
+ GeluOptions,
+ DynamicUpdateSliceOptions,
+ UnsortedSegmentProdOptions,
+ UnsortedSegmentMaxOptions,
+ UnsortedSegmentMinOptions,
+ UnsortedSegmentSumOptions,
+ ATan2Options,
+ SignOptions
+}
+
+// LINT.IfChange
+enum Padding : byte { SAME, VALID }
+// LINT.ThenChange(//tensorflow/compiler/mlir/lite/ir/tfl_op_enums.td)
+
+// LINT.IfChange
+enum ActivationFunctionType : byte {
+ NONE = 0,
+ RELU = 1,
+ RELU_N1_TO_1 = 2,
+ RELU6 = 3,
+ TANH = 4,
+ SIGN_BIT = 5,
+}
+// LINT.ThenChange(//tensorflow/compiler/mlir/lite/ir/tfl_op_enums.td)
+
+table Conv2DOptions {
+ padding:Padding;
+ stride_w:int;
+ stride_h:int;
+ fused_activation_function:ActivationFunctionType;
+ dilation_w_factor:int = 1;
+ dilation_h_factor:int = 1;
+}
+
+// Options for both Conv3D and Conv3DTranspose.
+table Conv3DOptions {
+ padding:Padding;
+ stride_d:int;
+ stride_w:int;
+ stride_h:int;
+ fused_activation_function:ActivationFunctionType;
+ dilation_d_factor:int = 1;
+ dilation_w_factor:int = 1;
+ dilation_h_factor:int = 1;
+}
+
+table Pool2DOptions {
+ padding:Padding;
+ stride_w:int;
+ stride_h:int;
+ filter_width:int;
+ filter_height:int;
+ fused_activation_function:ActivationFunctionType;
+}
+
+table DepthwiseConv2DOptions {
+ // Parameters for DepthwiseConv version 1 or above.
+ padding:Padding;
+ stride_w:int;
+ stride_h:int;
+ // `depth_multiplier` is redundant. It's used by CPU kernels in
+ // TensorFlow 2.0 or below, but ignored in versions above.
+ // See comments in lite/c/builtin_op_data.h for more details.
+ depth_multiplier:int;
+ fused_activation_function:ActivationFunctionType;
+ // Parameters for DepthwiseConv version 2 or above.
+ dilation_w_factor:int = 1;
+ dilation_h_factor:int = 1;
+}
+
+table ConcatEmbeddingsOptions {
+ num_channels:int;
+ num_columns_per_channel:[int];
+ embedding_dim_per_channel:[int]; // This could be inferred from parameters.
+}
+
+enum LSHProjectionType: byte {
+ UNKNOWN = 0,
+ SPARSE = 1,
+ DENSE = 2,
+}
+
+table LSHProjectionOptions {
+ type: LSHProjectionType;
+}
+
+table SVDFOptions {
+ rank:int;
+ fused_activation_function:ActivationFunctionType;
+ // For weights-only quantization, use asymmetric quantization for non
+ // constant inputs at evaluation time.
+ asymmetric_quantize_inputs:bool;
+}
+
+// An implementation of TensorFlow RNNCell.
+table RNNOptions {
+ fused_activation_function:ActivationFunctionType;
+ asymmetric_quantize_inputs:bool;
+}
+
+// An implementation of TensorFlow dynamic_rnn with RNNCell.
+table SequenceRNNOptions {
+ time_major:bool;
+ fused_activation_function:ActivationFunctionType;
+ asymmetric_quantize_inputs:bool;
+}
+
+// An implementation of TensorFlow bidrectional_dynamic_rnn with RNNCell.
+table BidirectionalSequenceRNNOptions {
+ time_major:bool;
+ fused_activation_function:ActivationFunctionType;
+ merge_outputs: bool;
+ asymmetric_quantize_inputs:bool;
+}
+
+// LINT.IfChange
+enum FullyConnectedOptionsWeightsFormat: byte {
+ DEFAULT = 0,
+ SHUFFLED4x16INT8 = 1,
+}
+// LINT.ThenChange(//tensorflow/compiler/mlir/lite/ir/tfl_op_enums.td)
+
+// An implementation of TensorFlow fully_connected (a.k.a Dense) layer.
+table FullyConnectedOptions {
+ // Parameters for FullyConnected version 1 or above.
+ fused_activation_function:ActivationFunctionType;
+
+ // Parameters for FullyConnected version 2 or above.
+ weights_format:FullyConnectedOptionsWeightsFormat = DEFAULT;
+
+ // Parameters for FullyConnected version 5 or above.
+ // If set to true, then the number of dimension is preserved. Furthermore,
+ // all but the last dimension of the input and output shapes will be equal.
+ keep_num_dims: bool;
+
+ // Parameters for FullyConnected version 7 or above.
+ // If set to true, then weights-only op will use asymmetric quantization for
+ // inputs.
+ asymmetric_quantize_inputs: bool;
+}
+
+table SoftmaxOptions {
+ beta: float;
+}
+
+// An implementation of TensorFlow concat.
+table ConcatenationOptions {
+ axis:int;
+ fused_activation_function:ActivationFunctionType;
+}
+
+table AddOptions {
+ fused_activation_function:ActivationFunctionType;
+ // Parameters supported by version 3.
+ pot_scale_int16:bool = true;
+}
+
+table MulOptions {
+ fused_activation_function:ActivationFunctionType;
+}
+
+table L2NormOptions {
+ // This field is currently ignored in the L2 Norm Op.
+ fused_activation_function:ActivationFunctionType;
+}
+
+table LocalResponseNormalizationOptions {
+ radius:int;
+ bias:float;
+ alpha:float;
+ beta:float;
+}
+
+// LINT.IfChange
+enum LSTMKernelType : byte {
+ // Full LSTM kernel which supports peephole and projection.
+ FULL = 0,
+ // Basic LSTM kernels. Equivalent to TensorFlow BasicLSTMCell.
+ BASIC = 1,
+}
+// LINT.ThenChange(//tensorflow/compiler/mlir/lite/ir/tfl_op_enums.td)
+
+// An implementation of TensorFlow LSTMCell and CoupledInputForgetGateLSTMCell
+table LSTMOptions {
+ // Parameters for LSTM version 1 or above.
+ fused_activation_function:ActivationFunctionType;
+ cell_clip: float; // Optional, 0.0 means no clipping
+ proj_clip: float; // Optional, 0.0 means no clipping
+
+ // Parameters for LSTM version 2 or above.
+ // Basic kernel is only supported in version 2 or above.
+ kernel_type: LSTMKernelType = FULL;
+
+ // Parameters for LSTM version 4 or above.
+ asymmetric_quantize_inputs: bool;
+}
+
+// An implementation of TensorFlow dynamic_rnn with LSTMCell.
+table UnidirectionalSequenceLSTMOptions {
+ fused_activation_function:ActivationFunctionType;
+ cell_clip: float; // Optional, 0.0 means no clipping
+ proj_clip: float; // Optional, 0.0 means no clipping
+
+ // If true then first dimension is sequence, otherwise batch.
+ time_major:bool;
+
+ // Parameter for Unidirectional Sequence LSTM version 3.
+ asymmetric_quantize_inputs:bool;
+
+ // Parameter for unidirectional sequence RNN version 4.
+ diagonal_recurrent_tensors:bool;
+}
+
+table BidirectionalSequenceLSTMOptions {
+ // Parameters supported by version 1:
+ fused_activation_function:ActivationFunctionType;
+ cell_clip: float; // Optional, 0.0 means no clipping
+ proj_clip: float; // Optional, 0.0 means no clipping
+
+ // If true, store the outputs of both directions into the first output.
+ merge_outputs: bool;
+
+ // Parameters supported by version 2:
+ // If true then first dimension is sequence, otherwise batch.
+ // Version 1 implementations assumed time_major to be true, so this default
+ // value should never change.
+ time_major: bool = true;
+
+ // Parameters for version 3 or above.
+ asymmetric_quantize_inputs:bool;
+}
+
+table ResizeBilinearOptions {
+ new_height: int (deprecated);
+ new_width: int (deprecated);
+ align_corners: bool;
+ half_pixel_centers: bool;
+}
+
+table ResizeNearestNeighborOptions {
+ align_corners: bool;
+ half_pixel_centers: bool;
+}
+
+// A call operation options
+table CallOptions {
+ // The subgraph index that needs to be called.
+ subgraph:uint;
+}
+
+table PadOptions {
+}
+
+table PadV2Options {
+}
+
+table ReshapeOptions {
+ new_shape:[int];
+}
+
+table SpaceToBatchNDOptions {
+}
+
+table BatchToSpaceNDOptions {
+}
+
+table SkipGramOptions {
+ ngram_size: int;
+ max_skip_size: int;
+ include_all_ngrams: bool;
+}
+
+table SpaceToDepthOptions {
+ block_size: int;
+}
+
+table DepthToSpaceOptions {
+ block_size: int;
+}
+
+table SubOptions {
+ fused_activation_function:ActivationFunctionType;
+ // Parameters supported by version 5
+ pot_scale_int16:bool = true;
+}
+
+table DivOptions {
+ fused_activation_function:ActivationFunctionType;
+}
+
+table TopKV2Options {
+}
+
+enum CombinerType : byte {
+ SUM = 0,
+ MEAN = 1,
+ SQRTN = 2,
+}
+
+table EmbeddingLookupSparseOptions {
+ combiner:CombinerType;
+}
+
+table GatherOptions {
+ axis: int;
+ // Parameters for Gather version 5 or above.
+ batch_dims: int = 0;
+}
+
+table TransposeOptions {
+}
+
+table ExpOptions {
+}
+
+table CosOptions {
+}
+
+table ReducerOptions {
+ keep_dims: bool;
+}
+
+table SqueezeOptions {
+ squeeze_dims:[int];
+}
+
+table SplitOptions {
+ num_splits: int;
+}
+
+table SplitVOptions {
+ num_splits: int;
+}
+
+table StridedSliceOptions {
+ begin_mask: int;
+ end_mask: int;
+ ellipsis_mask: int;
+ new_axis_mask: int;
+ shrink_axis_mask: int;
+}
+
+table LogSoftmaxOptions {
+}
+
+table CastOptions {
+ in_data_type: TensorType;
+ out_data_type: TensorType;
+}
+
+table DequantizeOptions {
+}
+
+table MaximumMinimumOptions {
+}
+
+table TileOptions {
+}
+
+table ArgMaxOptions {
+ output_type : TensorType;
+}
+
+table ArgMinOptions {
+ output_type : TensorType;
+}
+
+table GreaterOptions {
+}
+
+table GreaterEqualOptions {
+}
+
+table LessOptions {
+}
+
+table LessEqualOptions {
+}
+
+table NegOptions {
+}
+
+table SelectOptions {
+}
+
+table SliceOptions {
+}
+
+table TransposeConvOptions {
+ // Parameters supported by version 1, 2, 3:
+ padding:Padding;
+ stride_w:int;
+ stride_h:int;
+
+ // Parameters supported by version 4:
+ fused_activation_function:ActivationFunctionType = NONE;
+}
+
+table ExpandDimsOptions {
+}
+
+table SparseToDenseOptions {
+ validate_indices:bool;
+}
+
+table EqualOptions {
+}
+
+table NotEqualOptions {
+}
+
+table ShapeOptions {
+ // Optional output type of the operation (int32 or int64). Defaults to int32.
+ out_type : TensorType;
+}
+
+table RankOptions {
+}
+
+table PowOptions {
+}
+
+table FakeQuantOptions {
+ // Parameters supported by version 1:
+ min:float;
+ max:float;
+ num_bits:int;
+
+ // Parameters supported by version 2:
+ narrow_range:bool;
+}
+
+table PackOptions {
+ values_count:int;
+ axis:int;
+}
+
+table LogicalOrOptions {
+}
+
+table OneHotOptions {
+ axis:int;
+}
+
+table AbsOptions {
+}
+
+
+table HardSwishOptions {
+}
+
+table LogicalAndOptions {
+}
+
+table LogicalNotOptions {
+}
+
+table UnpackOptions {
+ num:int;
+ axis:int;
+}
+
+table FloorDivOptions {
+}
+
+table SquareOptions {
+}
+
+table ZerosLikeOptions {
+}
+
+table FillOptions {
+}
+
+table FloorModOptions {
+}
+
+table RangeOptions {
+}
+
+table LeakyReluOptions {
+ alpha:float;
+}
+
+table SquaredDifferenceOptions {
+}
+
+// LINT.IfChange
+enum MirrorPadMode : byte {
+ // Doesn't include borders.
+ REFLECT = 0,
+ // Includes borders.
+ SYMMETRIC = 1,
+}
+// LINT.ThenChange(//tensorflow/compiler/mlir/lite/ir/tfl_op_enums.td)
+
+table MirrorPadOptions {
+ mode:MirrorPadMode;
+}
+
+table UniqueOptions {
+ idx_out_type:TensorType = INT32;
+}
+
+table ReverseV2Options {
+}
+
+table AddNOptions {
+}
+
+table GatherNdOptions {
+}
+
+table WhereOptions {
+}
+
+table ReverseSequenceOptions {
+ seq_dim:int;
+ batch_dim:int = 0;
+}
+
+table MatrixDiagOptions {
+}
+
+table QuantizeOptions {
+}
+
+table MatrixSetDiagOptions {
+}
+
+table IfOptions {
+ then_subgraph_index:int;
+ else_subgraph_index:int;
+}
+
+table CallOnceOptions {
+ init_subgraph_index:int;
+}
+
+table WhileOptions {
+ cond_subgraph_index:int;
+ body_subgraph_index:int;
+}
+
+table NonMaxSuppressionV4Options {
+}
+
+table NonMaxSuppressionV5Options {
+}
+
+table ScatterNdOptions {
+}
+
+table SelectV2Options {
+}
+
+table DensifyOptions {
+}
+
+table SegmentSumOptions {
+}
+
+table BatchMatMulOptions {
+ adj_x:bool;
+ adj_y:bool;
+ // Parameters for BatchMatMul version 4 or above.
+ // If set to true, then weights-only op will use asymmetric quantization for
+ // inputs.
+ asymmetric_quantize_inputs: bool;
+}
+
+table CumsumOptions {
+ exclusive:bool;
+ reverse:bool;
+}
+
+table BroadcastToOptions {
+}
+
+table Rfft2dOptions {
+}
+
+table HashtableOptions {
+ // The identity of hash tables. This identity will be used across different
+ // subgraphs in the same interpreter instance.
+ table_id:int;
+ key_dtype:TensorType;
+ value_dtype:TensorType;
+}
+
+table HashtableFindOptions {
+}
+
+table HashtableImportOptions {
+}
+
+table HashtableSizeOptions {
+}
+
+table VarHandleOptions {
+ container:string;
+ shared_name:string;
+}
+
+table ReadVariableOptions {
+}
+
+table AssignVariableOptions {
+}
+
+table RandomOptions {
+ seed: long;
+ seed2: long;
+}
+
+table BucketizeOptions {
+ boundaries: [float]; // The bucket boundaries.
+}
+
+table GeluOptions {
+ approximate: bool;
+}
+
+table DynamicUpdateSliceOptions {
+}
+
+table UnsortedSegmentProdOptions {
+}
+
+table UnsortedSegmentMaxOptions {
+}
+
+table UnsortedSegmentSumOptions {
+}
+
+table ATan2Options {
+}
+
+table UnsortedSegmentMinOptions{
+}
+
+table SignOptions {
+}
+
+
+// An OperatorCode can be an enum value (BuiltinOperator) if the operator is a
+// builtin, or a string if the operator is custom.
+table OperatorCode {
+ // This field is for backward compatibility. This field will be used when
+ // the value of the extended builtin_code field has less than
+ // BulitinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES.
+ deprecated_builtin_code:byte;
+ custom_code:string;
+
+ // The version of the operator. The version need to be bumped whenever new
+ // parameters are introduced into an op.
+ version:int = 1;
+
+ // This field is introduced for resolving op builtin code shortage problem
+ // (the original BuiltinOperator enum field was represented as a byte).
+ // This field will be used when the value of the extended builtin_code field
+ // has greater than BulitinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES.
+ builtin_code:BuiltinOperator;
+}
+
+enum CustomOptionsFormat : byte {
+ FLEXBUFFERS = 0,
+}
+
+// An operator takes tensors as inputs and outputs. The type of operation being
+// performed is determined by an index into the list of valid OperatorCodes,
+// while the specifics of each operations is configured using builtin_options
+// or custom_options.
+table Operator {
+ // Index into the operator_codes array. Using an integer here avoids
+ // complicate map lookups.
+ opcode_index:uint;
+
+ // Optional input are indicated by -1.
+ inputs:[int];
+ outputs:[int];
+
+ builtin_options:BuiltinOptions;
+ custom_options:[ubyte];
+ custom_options_format:CustomOptionsFormat;
+
+ // A list of booleans indicating the input tensors which are being mutated by
+ // this operator.(e.g. used by RNN and LSTM).
+ // For example, if the "inputs" array refers to 5 tensors and the second and
+ // fifth are mutable variables, then this list will contain
+ // [false, true, false, false, true].
+ //
+ // If the list is empty, no variable is mutated in this operator.
+ // The list either has the same length as `inputs`, or is empty.
+ mutating_variable_inputs:[bool];
+
+ // A list of indices to the subgraph's "tensors" that are internal to an Op.
+ // Internal tensors are those that do not flow in or out of the operation,
+ // but instead are part of internal computation. As such, the operation's
+ // implementation may manage its memory more efficiently. They are needed
+ // however (i.e. not just an implementation detail) since they are part of the
+ // computation, which may require relevant metadata such as quantization
+ // parameters.
+ intermediates:[int];
+}
+
+// The root type, defining a subgraph, which typically represents an entire
+// model.
+table SubGraph {
+ // A list of all tensors used in this subgraph.
+ tensors:[Tensor];
+
+ // Indices of the tensors that are inputs into this subgraph. Note this is
+ // the list of non-static tensors that feed into the subgraph for inference.
+ inputs:[int];
+
+ // Indices of the tensors that are outputs out of this subgraph. Note this is
+ // the list of output tensors that are considered the product of the
+ // subgraph's inference.
+ outputs:[int];
+
+ // All operators, in execution order.
+ operators:[Operator];
+
+ // Name of this subgraph (used for debugging).
+ name:string;
+}
+
+// Table of raw data buffers (used for constant tensors). Referenced by tensors
+// by index. The generous alignment accommodates mmap-friendly data structures.
+table Buffer {
+ data:[ubyte] (force_align: 16);
+}
+
+table Metadata {
+ // A human readable string to uniquely identify a Metadata.
+ name:string;
+ // An index to the buffers table.
+ buffer:uint;
+}
+
+// Map from an alias name of tensor to tensor index in the graph.
+// This is used in Signature def.
+table TensorMap {
+ // Represents the alias to use for this tensor.
+ name:string;
+
+ // The actual tensor index in the primary graph, that 'name' corresponds to.
+ tensor_index:uint;
+}
+
+// This corresponds to SignatureDef in Tensorflow SavedModel.
+// The SignatureDef will be part of the SavedModel provided for conversion.
+table SignatureDef {
+ // Named inputs for this signature.
+ inputs:[TensorMap];
+
+ // Named outputs for this signature.
+ outputs:[TensorMap];
+
+ // Key value which was in the Tensorflow SavedModel SignatureDef map.
+ signature_key:string;
+
+ // Model tag, deprecated.
+ deprecated_tag:string (deprecated);
+
+ // Index of subgraphs that corresponds to the exported method.
+ subgraph_index:uint;
+}
+
+table Model {
+ // Version of the schema.
+ version:uint;
+
+ // A list of all operator codes used in this model. This is
+ // kept in order because operators carry an index into this
+ // vector.
+ operator_codes:[OperatorCode];
+
+ // All the subgraphs of the model. The 0th is assumed to be the main
+ // model.
+ subgraphs:[SubGraph];
+
+ // A description of the model.
+ description:string;
+
+ // Buffers of the model.
+ // Note the 0th entry of this array must be an empty buffer (sentinel).
+ // This is a convention so that tensors without a buffer can provide 0 as
+ // their buffer.
+ buffers:[Buffer];
+
+ // Metadata about the model. Indirects into the existings buffers list.
+ // Deprecated, prefer to use metadata field.
+ metadata_buffer:[int];
+
+ // Metadata about the model.
+ metadata:[Metadata];
+
+ // Optional SignatureDefs for the model.
+ signature_defs:[SignatureDef];
+}
+
+root_type Model;
diff --git a/res/TensorFlowLiteSchema/SCHEMA.lst b/res/TensorFlowLiteSchema/SCHEMA.lst
index 609ef4b0b..d7308eeea 100644
--- a/res/TensorFlowLiteSchema/SCHEMA.lst
+++ b/res/TensorFlowLiteSchema/SCHEMA.lst
@@ -7,3 +7,4 @@ VERSION,URL
2.3.0-rc0,https://raw.githubusercontent.com/tensorflow/tensorflow/v2.3.0-rc0/tensorflow/lite/schema/schema.fbs
2.3.0,https://raw.githubusercontent.com/tensorflow/tensorflow/v2.3.0/tensorflow/lite/schema/schema.fbs
2.6.0,https://raw.githubusercontent.com/tensorflow/tensorflow/v2.6.0/tensorflow/lite/schema/schema.fbs
+2.10.1,https://raw.githubusercontent.com/tensorflow/tensorflow/v2.10.1/tensorflow/lite/schema/schema.fbs
diff --git a/runtime/contrib/android/api/build.gradle b/runtime/contrib/android/api/build.gradle
index cd5e20522..eed8f274e 100644
--- a/runtime/contrib/android/api/build.gradle
+++ b/runtime/contrib/android/api/build.gradle
@@ -8,7 +8,7 @@ android {
minSdkVersion 26
targetSdkVersion 29
versionCode 1
- versionName "1.22.1"
+ versionName "1.25.0"
externalNativeBuild {
ndkBuild {
diff --git a/runtime/libs/benchmark/include/benchmark/CsvWriter.h b/runtime/libs/benchmark/include/benchmark/CsvWriter.h
index 5c259d7ed..d926bad8f 100644
--- a/runtime/libs/benchmark/include/benchmark/CsvWriter.h
+++ b/runtime/libs/benchmark/include/benchmark/CsvWriter.h
@@ -17,6 +17,7 @@
#ifndef __NNFW_BENCHMARK_CSV_WRITER_H__
#define __NNFW_BENCHMARK_CSV_WRITER_H__
+#include <cstdint>
#include <vector>
#include <string>
#include <fstream>
diff --git a/runtime/libs/benchmark/include/benchmark/Phase.h b/runtime/libs/benchmark/include/benchmark/Phase.h
index 5eceb04c5..9b91a4391 100644
--- a/runtime/libs/benchmark/include/benchmark/Phase.h
+++ b/runtime/libs/benchmark/include/benchmark/Phase.h
@@ -19,6 +19,7 @@
#include "Types.h"
+#include <cstdint>
#include <string>
#include <vector>
diff --git a/runtime/libs/benchmark/src/Result.cpp b/runtime/libs/benchmark/src/Result.cpp
index 03566874e..04925f4d2 100644
--- a/runtime/libs/benchmark/src/Result.cpp
+++ b/runtime/libs/benchmark/src/Result.cpp
@@ -57,7 +57,7 @@ double minTimeMs(const benchmark::Phase &phase)
double geomeanTimeMs(const benchmark::Phase &phase)
{
double log_sum = 0.0;
- for (auto t_us : phase.time)
+ for (auto &&t_us : phase.time)
{
log_sum += std::log(t_us / 1e3);
}
diff --git a/runtime/onert/CMakeLists.txt b/runtime/onert/CMakeLists.txt
index 3c9ca99da..74f7ae568 100644
--- a/runtime/onert/CMakeLists.txt
+++ b/runtime/onert/CMakeLists.txt
@@ -6,4 +6,5 @@ add_subdirectory(backend)
add_subdirectory(frontend)
add_subdirectory(core)
add_subdirectory(api)
+add_subdirectory(odc)
add_subdirectory(sample)
diff --git a/runtime/onert/api/include/nnfw.h b/runtime/onert/api/include/nnfw.h
index 658cba4d5..1f1541a7e 100644
--- a/runtime/onert/api/include/nnfw.h
+++ b/runtime/onert/api/include/nnfw.h
@@ -243,11 +243,11 @@ NNFW_STATUS nnfw_apply_tensorinfo(nnfw_session *session, uint32_t index,
/**
* @brief Set input model's tensor info for resizing
*
- * This function can be called at any time after calling {@link nnfw_model_load_from_file}. Changing
+ * This function can be called at any time after calling {@link nnfw_load_model_from_file}. Changing
* input tensor's shape will cause shape inference for the model. There are two different types of
* shape inference - static and dynamic. Which one to use is depend on the current state of the
* session.
- * When it is called after calling {@link nnfw_model_load_from_file} and before calling {@link
+ * When it is called after calling {@link nnfw_load_model_from_file} and before calling {@link
* nnfw_prepare}, this info will be used when {@link nnfw_prepare}. And it will perform static shape
* inference for all tensors.
* When it is called after calling {@link nnfw_prepare} or even after {@link nnfw_run}, this info
@@ -266,7 +266,7 @@ NNFW_STATUS nnfw_set_input_tensorinfo(nnfw_session *session, uint32_t index,
* @brief Prepare session to be ready for inference
*
* This phase may finalize model compilation, scheduling, and additional settings.
- * If {@link nnfw_apply_tensor} is called to apply input tensor info different with model
+ * If {@link nnfw_apply_tensorinfo} is called to apply input tensor info different with model
* before this function, tries to resize all tensors.
*
* @param[in] session the session to be prepared
@@ -309,7 +309,7 @@ NNFW_STATUS nnfw_run_async(nnfw_session *session);
/**
* @brief Wait for asynchronous run to finish
*
- * <p>This function must be called after calling {@link nnfw_run_asnyc}, and can be called only once
+ * <p>This function must be called after calling {@link nnfw_run_async}, and can be called only once
* for a {@link nnfw_run_async} call.
*
* <p>When this function returns, it means that this session has finished the asynchronous run. Then
@@ -496,7 +496,7 @@ NNFW_STATUS nnfw_set_op_backend(nnfw_session *session, const char *op, const cha
* @note: The input session could be null for global information (e.g. runtime version).*
*
* @param[in] session session to be queried on.
- * @param[in] information ID to be queried
+ * @param[in] id ID to be queried
* @param[out] val uint32 value to be returned.
*
* @return @c NNFW_STATUS_NO_ERROR if successful
diff --git a/runtime/onert/api/include/nnfw_experimental.h b/runtime/onert/api/include/nnfw_experimental.h
index b20447e9e..3c8b08f52 100644
--- a/runtime/onert/api/include/nnfw_experimental.h
+++ b/runtime/onert/api/include/nnfw_experimental.h
@@ -19,6 +19,10 @@
#include "nnfw.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
// Used for custom kernel development
/*
@@ -152,4 +156,244 @@ NNFW_STATUS nnfw_push_pipeline_input(nnfw_session *session, void *inputs, void *
*/
NNFW_STATUS nnfw_pop_pipeline_output(nnfw_session *session, void *outputs);
+/**
+ * Training C APIs
+ *
+ * Training APIs are designed to be used in the following order for training
+ * 1. nnfw_train_prepare
+ * 2. nnfw_train_set_input, nnfw_train_set_expected for inputs & expected outputs
+ * 3. nnfw_train
+ * 4. nnfw_train_get_loss
+ *
+ * If you want to inference after training with the same session, you can use the following order
+ * 1. nnfw_set_input
+ * 2. nnfw_set_output
+ * 3. nnfw_run
+ */
+
+//////////////////////////////////////////////
+// Essential APIs for training
+//////////////////////////////////////////////
+typedef enum
+{
+ NNFW_TRAIN_LOSS_MEAN_SQUARED_ERROR = 0,
+ NNFW_TRAIN_LOSS_CATEGORICAL_CROSSENTROPY = 1,
+} NNFW_TRAIN_LOSS;
+
+typedef enum
+{
+ NNFW_TRAIN_OPTIMIZER_SGD = 0,
+ NNFW_TRAIN_OPTIMIZER_ADAM = 1,
+} NNFW_TRAIN_OPTIMIZER;
+
+/**
+ * @brief Training information to prepare training
+ * @todo Add more training information
+ * (e.g. optimizer, loss function, ...)
+ */
+typedef struct nnfw_train_info
+{
+ /** Learning rate */
+ float learning_rate = 0.001f;
+ /** Batch size */
+ uint32_t batch_size = 1;
+ /** loss type */
+ NNFW_TRAIN_LOSS loss = NNFW_TRAIN_LOSS_MEAN_SQUARED_ERROR;
+ /** optimizer type */
+ NNFW_TRAIN_OPTIMIZER opt = NNFW_TRAIN_OPTIMIZER_SGD;
+} nnfw_train_info;
+
+/**
+ * @brief Prepare session to be ready for training
+ * @note The session will be entered into training mode
+ *
+ * @param[in] session The session to be prepared for training
+ * @param[in] info Training information.
+ * If info is nullptr, it will not change training information.
+ * If it is nullptr and model has not training information,
+ * it will use default training information.
+ * Default training information is {learning_rate = 0.001f, batch_size = 1}
+ *
+ * @return @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_train_prepare(nnfw_session *session, const nnfw_train_info *info);
+
+/**
+ * @brief Set training input
+ * @note This function should be called after {@link nnfw_train_prepare}
+ *
+ * @param[in] session The session to be set training inputs and expected model outputs
+ * @param[in] index The index of training input
+ * @param[in] input The input buffers for training
+ * @param[in] input_info The shape and type of input buffer
+ * If it is nullptr, it will not change shape and batch size
+ * @return @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_train_set_input(nnfw_session *session, uint32_t index, const void *input,
+ const nnfw_tensorinfo *input_info);
+
+/**
+ * @brief Set training expected output
+ * @note This function should be called after {@link nnfw_train_prepare}
+ *
+ * @param session The session to be set training inputs and expected model outputs
+ * @param index The index of training expected output
+ * @param expected The expected buffers for training
+ * @param expected_info The shape and type of expected buffer
+ * If it is nullptr, it will not change shape and batch size
+ * @return @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_train_set_expected(nnfw_session *session, uint32_t index, const void *expected,
+ const nnfw_tensorinfo *expected_info);
+
+/**
+ * @brief Train the model
+ * @note This function should be called after {@link nnfw_train_set_input} and
+ * {@link nnfw_train_set_expected} for each input and expected output
+ *
+ * @param[in] session The session to be trained
+ * @param[in] update_weights If true, update weights of the model
+ * If false, do not update weights of the model (for validation)
+ * @return @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_train(nnfw_session *session, bool update_weights);
+
+/**
+ * @brief Get loss value for expected output
+ * @note This function should be called after {@link nnfw_train}
+ *
+ * @param[in] session The session to get loss value
+ * @param[in] index The index of loss value [0, number of expected outputs)
+ * @param[out] loss The loss value
+ * @return @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_train_get_loss(nnfw_session *session, uint32_t index, float *loss);
+
+/**
+ * @brief Export circle model
+ * @note This function should be called on training mode
+ * This function should be called after {@link nnfw_train}
+ *
+ * @param[in] session The session to export inference model
+ * @param[in] path The path to export inference model
+ * @return @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_train_export_circle(nnfw_session *session, const char *path);
+
+//////////////////////////////////////////////
+// Optional APIs for training
+//////////////////////////////////////////////
+
+/**
+ * @brief Get the training model input information
+ * @note This function should be called after {@link nnfw_train_prepare}
+ *
+ * @param[in] session The session to get the training model input information
+ * @param[in] index The index of training model input
+ * @param[out] info The shape and type of training model input
+ * @return @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_train_input_tensorinfo(nnfw_session *session, uint32_t index,
+ nnfw_tensorinfo *info);
+
+/**
+ * @brief Get the training model expected output information
+ * @note This function should be called after {@link nnfw_train_prepare}
+ *
+ * @param[in] session The session to get the training model expected output information
+ * @param[in] index The index of training model expected output
+ * @param[out] info The shape and type of training model expected output
+ * @return @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_train_expected_tensorinfo(nnfw_session *session, uint32_t index,
+ nnfw_tensorinfo *info);
+
+//////////////////////////////////////////////
+// Not planned to be implemented
+//////////////////////////////////////////////
+
+/**
+ * @brief Convert between training mode and inference mode
+ * @note This function should be called after {@link nnfw_train} or {@link nnfw_prepare}
+ *
+ * @param[in] session The session to convert training mode to inference mode
+ * @param[in] train If false, convert training model to inference model
+ * If true, convert inference model to training model
+ * @return @c NNFW_STATUS_NO_ERROR if successful
+ */
+// NNFW_STATUS nnfw_set_training_mode(nnfw_session *session, bool train);
+
+/**
+ * @brief Set training information after prepare training
+ * @note This function may be used after {@link nnfw_train_prepare}
+ *
+ * @param[in] session The session prepared for training
+ * @param[in] info Training information
+ * @return @c NNFW_STATUS_NO_ERROR if successful
+ */
+// NNFW_STATUS nnfw_train_set_traininfo(nnfw_session *session, const nnfw_train_info info);
+
+/**
+ * On-Device Quantization APIs
+ *
+ * On-Device Quantization APIs are designed to be used in the following order
+ * 1. nnfw_set_quantization_type
+ * 2. nnfw_set_quantized_model_path
+ * 3. nnfw_quantize
+ *
+ * You should use Quantization APIs after {@link nnfw_load_model_from_file},
+ * before {@link nnfw_prepare} and {@link nnfw_set_input_tensorinfo}.
+ */
+
+/**
+ * @brief quantization type
+ */
+typedef enum
+{
+ /** default value: type not set */
+ NNFW_QUANTIZE_TYPE_NOT_SET,
+ /** asymmetric quantization with a scale and zero point */
+ NNFW_QUANTIZE_TYPE_U8_ASYM,
+ /** symmetric quantization with a scale only */
+ NNFW_QUANTIZE_TYPE_I16_SYM,
+} NNFW_QUANTIZE_TYPE;
+
+/**
+ * @brief Set quantization type
+ *
+ * This function should be called before {@link nnfw_quantize} is invoked.
+ *
+ * @param[in] session nnfw_session to set quantization type
+ * @param[in] pref @c NNFW_QUANTIZE_TYPE
+ * @return @c NNFW_STATUS_NO_ERROR if successful,
+ * @c NNFW_STATUS_UNEXPECTED_NULL if session is null,
+ * otherwise return @c NNFW_STATUS_ERROR
+ */
+NNFW_STATUS nnfw_set_quantization_type(nnfw_session *session, NNFW_QUANTIZE_TYPE qtype);
+
+/**
+ * @brief Set exported quantized model path
+ *
+ * This function should be called before {@link nnfw_quantize} is invoked.
+ *
+ * TODO: If this function is not called, quantized model will not be exported
+ *
+ * @param[in] session nnfw_session to set quantized model path
+ * @param[in] path Quantized model path
+ * @return @c NNFW_STATUS_NO_ERROR if successful, otherwise return @c NNFW_STATUS_ERROR
+ */
+NNFW_STATUS nnfw_set_quantized_model_path(nnfw_session *session, const char *path);
+
+/**
+ * @brief Quantize circle model
+ *
+ * @param[in] session nnfw_session to quantize
+ * @return @c ODC_STATUS_NO_ERROR if successful, otherwise return @c ODC_STATUS_ERROR
+ */
+NNFW_STATUS nnfw_quantize(nnfw_session *session);
+
+#ifdef __cplusplus
+}
+#endif
+
#endif // __NNFW_EXPERIMENTAL_H__
diff --git a/runtime/onert/api/include/nnfw_version.h b/runtime/onert/api/include/nnfw_version.h
index db35c6700..7a280a66d 100644
--- a/runtime/onert/api/include/nnfw_version.h
+++ b/runtime/onert/api/include/nnfw_version.h
@@ -21,6 +21,6 @@
* NNFW_VERSION is a uint32 value representing nnfw runtime version
* in 0xMMmmmmPP, where MM = major, mmmm = minor, PP = patch
*/
-#define NNFW_VERSION 0x01001601
+#define NNFW_VERSION 0x01001900
#endif // __NNFW_VERSION_H__
diff --git a/runtime/onert/api/src/nnfw_api.cc b/runtime/onert/api/src/nnfw_api.cc
index a0e6ee094..185738add 100644
--- a/runtime/onert/api/src/nnfw_api.cc
+++ b/runtime/onert/api/src/nnfw_api.cc
@@ -385,3 +385,133 @@ NNFW_STATUS nnfw_pop_pipeline_output(nnfw_session *session, void *outputs)
NNFW_RETURN_ERROR_IF_NULL(session);
return session->pop_pipeline_output((std::vector<void *> *)outputs);
}
+
+// Training
+
+#ifdef ONERT_TRAIN
+
+NNFW_STATUS nnfw_train_prepare(nnfw_session *session, const nnfw_train_info *info)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->train_prepare(info);
+}
+
+NNFW_STATUS nnfw_train_input_tensorinfo(nnfw_session *session, uint32_t index,
+ nnfw_tensorinfo *info)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->train_input_tensorinfo(index, info);
+}
+
+NNFW_STATUS nnfw_train_expected_tensorinfo(nnfw_session *session, uint32_t index,
+ nnfw_tensorinfo *info)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->train_expected_tensorinfo(index, info);
+}
+
+NNFW_STATUS nnfw_train_set_input(nnfw_session *session, uint32_t index, const void *input,
+ const nnfw_tensorinfo *input_info)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->train_set_input(index, input, input_info);
+}
+
+NNFW_STATUS nnfw_train_set_expected(nnfw_session *session, uint32_t index, const void *expected,
+ const nnfw_tensorinfo *expected_info)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->train_set_expected(index, expected, expected_info);
+}
+
+NNFW_STATUS nnfw_train(nnfw_session *session, bool update_weights)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->train_run(update_weights);
+}
+
+NNFW_STATUS nnfw_train_get_loss(nnfw_session *session, uint32_t index, float *loss)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->train_get_loss(index, loss);
+}
+
+NNFW_STATUS nnfw_train_export_circle(nnfw_session *session, const char *path)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->train_export_circle(path);
+}
+
+#else // ONERT_TRAIN
+
+NNFW_STATUS nnfw_train_prepare(nnfw_session *session, const nnfw_train_info *)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return NNFW_STATUS_ERROR;
+}
+
+NNFW_STATUS nnfw_train_input_tensorinfo(nnfw_session *session, uint32_t, nnfw_tensorinfo *)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return NNFW_STATUS_ERROR;
+}
+
+NNFW_STATUS nnfw_train_expected_tensorinfo(nnfw_session *session, uint32_t, nnfw_tensorinfo *)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return NNFW_STATUS_ERROR;
+}
+
+NNFW_STATUS nnfw_train_set_input(nnfw_session *session, uint32_t, const void *,
+ const nnfw_tensorinfo *)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return NNFW_STATUS_ERROR;
+}
+
+NNFW_STATUS nnfw_train_set_expected(nnfw_session *session, uint32_t, const void *,
+ const nnfw_tensorinfo *)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return NNFW_STATUS_ERROR;
+}
+
+NNFW_STATUS nnfw_train(nnfw_session *session, bool)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return NNFW_STATUS_ERROR;
+}
+
+NNFW_STATUS nnfw_train_get_loss(nnfw_session *session, uint32_t, float *)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return NNFW_STATUS_ERROR;
+}
+
+NNFW_STATUS nnfw_train_export_circle(nnfw_session *session, const char *)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return NNFW_STATUS_ERROR;
+}
+
+#endif // ONERT_TRAIN
+
+// Quantization
+
+NNFW_STATUS nnfw_set_quantization_type(nnfw_session *session, NNFW_QUANTIZE_TYPE qtype)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->set_quantization_type(qtype);
+}
+
+NNFW_STATUS nnfw_set_quantized_model_path(nnfw_session *session, const char *path)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->set_quantized_model_path(path);
+}
+
+NNFW_STATUS nnfw_quantize(nnfw_session *session)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->quantize();
+}
diff --git a/runtime/onert/api/src/nnfw_api_internal.cc b/runtime/onert/api/src/nnfw_api_internal.cc
index 8eedb5314..fc02a9227 100644
--- a/runtime/onert/api/src/nnfw_api_internal.cc
+++ b/runtime/onert/api/src/nnfw_api_internal.cc
@@ -28,6 +28,7 @@
#include "ir/NNPkg.h"
#include "ir/OpCode.h"
#include "util/TracingCtx.h"
+#include "odc/QuantizeManager.h"
#include <fstream>
#include <iostream>
@@ -73,7 +74,7 @@ onert::ir::Layout convertLayout(NNFW_LAYOUT layout)
return onert::ir::Layout::UNKNOWN;
}
-NNFW_STATUS getTensorIndexImpl(const onert::ir::Graph &graph, const char *tensorname,
+NNFW_STATUS getTensorIndexImpl(const onert::ir::IGraph &graph, const char *tensorname,
uint32_t *index, bool is_input)
{
if (!tensorname || !index)
@@ -195,11 +196,34 @@ std::unique_ptr<onert::ir::Model> loadModel(const std::string filename,
return std::unique_ptr<onert::ir::Model>(nullptr);
}
+#ifdef ONERT_TRAIN
+uint64_t getBufSize(const nnfw_tensorinfo *info)
+{
+ static int elmsize[] = {
+ sizeof(float), /* NNFW_TYPE_TENSOR_FLOAT32 = 0 */
+ sizeof(int), /* NNFW_TYPE_TENSOR_INT32 = 1 */
+ sizeof(uint8_t), /* NNFW_TYPE_TENSOR_QUANT8_ASYMM = 2 */
+ sizeof(bool), /* NNFW_TYPE_TENSOR_BOOL = 3 */
+ sizeof(uint8_t), /* NNFW_TYPE_TENSOR_UINT8 = 4 */
+ sizeof(int64_t), /* NNFW_TYPE_TENSOR_INT64 = 5 */
+ sizeof(int8_t), /* NNFW_TYPE_TENSOR_QUANT8_ASYMM_SIGNED = 6 */
+ sizeof(int16_t), /* NNFW_TYPE_TENSOR_QUANT16_SYMM_SIGNED = 7 */
+ };
+
+ uint64_t n = 1;
+ for (int32_t i = 0; i < info->rank; ++i)
+ {
+ assert(info->dims[i] >= 0);
+ n *= info->dims[i];
+ }
+ return elmsize[info->dtype] * n;
+}
+#endif // ONERT_TRAIN
} // namespace
nnfw_session::nnfw_session()
: _nnpkg{nullptr}, _coptions{}, _compiler_artifact{nullptr}, _execution{nullptr},
- _kernel_registry{nullptr}
+ _kernel_registry{nullptr}, _quant_manager{nullptr}
{
// DO NOTHING
}
@@ -268,6 +292,9 @@ NNFW_STATUS nnfw_session::load_model_from_modelfile(const char *model_file_path)
return NNFW_STATUS_UNEXPECTED_NULL;
}
+ // Create quantize manager
+ _quant_manager = std::make_unique<onert::odc::QuantizeManager>(std::string(model_file_path));
+
std::string filename{model_file_path};
// TODO: Use std::filesystem::path when we can use c++17.
auto dotidx = filename.find_last_of('.');
@@ -352,6 +379,11 @@ NNFW_STATUS nnfw_session::load_model_from_nnpackage(const char *package_dir)
return NNFW_STATUS_ERROR;
}
+ // Create quantize manager
+ // TODO Support multiple models
+ auto const model_filename = package_path + std::string("/") + models[0].asString();
+ _quant_manager = std::make_unique<onert::odc::QuantizeManager>(model_filename);
+
for (uint16_t i = 0; i < num_models; ++i)
{
auto model_file_path = package_path + std::string("/") + models[i].asString();
@@ -359,7 +391,7 @@ NNFW_STATUS nnfw_session::load_model_from_nnpackage(const char *package_dir)
auto model = loadModel(model_file_path, model_type);
if (model == nullptr)
return NNFW_STATUS_ERROR;
- model->primary_subgraph()->bindKernelBuilder(_kernel_registry->getBuilder());
+ model->bindKernelBuilder(_kernel_registry->getBuilder());
_nnpkg->push(onert::ir::ModelIndex{i}, std::move(model));
_coptions.push_back(onert::compiler::CompilerOptions::fromGlobalConfig());
}
@@ -697,8 +729,7 @@ NNFW_STATUS nnfw_session::apply_tensorinfo(uint32_t index, nnfw_tensorinfo ti)
{
// In this case, if we apply input shape, it will propagate after compilation and excution
- auto &info = _nnpkg->inputInfo(index);
- info.shape(new_shape);
+ _nnpkg->changeInputShape(index, new_shape);
}
else // when called after nnfw_session::prepare()
_execution->changeInputShape(onert::ir::IOIndex(index), new_shape);
@@ -941,7 +972,7 @@ NNFW_STATUS nnfw_session::set_config(const char *key, const char *value)
return NNFW_STATUS_NO_ERROR;
}
-const onert::ir::Graph *nnfw_session::primary_subgraph()
+const onert::ir::IGraph *nnfw_session::primary_subgraph()
{
if (_nnpkg != nullptr)
{
@@ -1129,3 +1160,400 @@ NNFW_STATUS nnfw_session::set_backends_per_operation(const char *backend_setting
return NNFW_STATUS_NO_ERROR;
}
+
+#ifdef ONERT_TRAIN
+NNFW_STATUS nnfw_session::train_prepare(const nnfw_train_info *info)
+{
+ // We may need different state to represent training model is loaded
+ if (!isStateModelLoaded())
+ {
+ std::cerr << "Error during model prepare training: ";
+ if (_state == State::PREPARED_TRAINING)
+ std::cerr << "prepare should be run once";
+ else
+ std::cerr << "invalid state";
+ std::cerr << std::endl;
+ return NNFW_STATUS_INVALID_STATE;
+ }
+
+ try
+ {
+ nnfw_train_info tinfo;
+ if (info != nullptr)
+ {
+ tinfo = *info;
+ }
+
+ auto convertLossType = [](const int &type) {
+ if (type == NNFW_TRAIN_LOSS_MEAN_SQUARED_ERROR)
+ return onert::ir::operation::Loss::Type::MEAN_SQUARED_ERROR;
+ if (type == NNFW_TRAIN_LOSS_CATEGORICAL_CROSSENTROPY)
+ return onert::ir::operation::Loss::Type::CATEGORICAL_CROSSENTROPY;
+ else
+ throw std::runtime_error("not supported loss type");
+ };
+ onert::compiler::train::LossInfo loss_info;
+ loss_info.type = convertLossType(tinfo.loss);
+
+ auto convertOptType = [](const int &type) {
+ if (type == NNFW_TRAIN_OPTIMIZER_SGD)
+ return onert::exec::train::optimizer::OptimizerCode::SGD;
+ else if (type == NNFW_TRAIN_OPTIMIZER_ADAM)
+ return onert::exec::train::optimizer::OptimizerCode::Adam;
+ else
+ throw std::runtime_error("not supported optimizer type");
+ };
+ onert::compiler::train::OptimizerInfo opt_info;
+ opt_info.learning_rate = tinfo.learning_rate;
+ opt_info.optim_code = convertOptType(tinfo.opt);
+
+ onert::compiler::train::TrainingInfo training_info;
+ training_info.setBatchSize(tinfo.batch_size);
+ training_info.setLossInfo(loss_info);
+ training_info.setOptimizerInfo(opt_info);
+
+ auto compiler =
+ onert::compiler::CompilerFactory::get().create(_nnpkg, _coptions, &training_info);
+ _nnpkg.reset();
+ _compiler_artifact = compiler->compile();
+ _execution = std::make_unique<onert::exec::Execution>(_compiler_artifact->_executors);
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Error during nnfw_session::train_prepare : " << e.what() << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+
+ _state = State::PREPARED_TRAINING;
+ return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::train_input_tensorinfo(uint32_t index, nnfw_tensorinfo *ti)
+{
+ if (!isStatePreparedOrFinishedTraining())
+ {
+ std::cerr << "Error during nnfw_session::train_input_tensorinfo : invalid state" << std::endl;
+ return NNFW_STATUS_INVALID_STATE;
+ }
+
+ // Check index is valid: [0, getInputSize())
+
+ // NYI
+ (void)index;
+ (void)ti;
+ return NNFW_STATUS_ERROR;
+}
+
+NNFW_STATUS nnfw_session::train_expected_tensorinfo(uint32_t index, nnfw_tensorinfo *ti)
+{
+ if (!isStatePreparedOrFinishedTraining())
+ {
+ std::cerr << "Error during nnfw_session::train_expected_tensorinfo : invalid state"
+ << std::endl;
+ return NNFW_STATUS_INVALID_STATE;
+ }
+
+ // Check index is valid: [0, getExpectedSize())
+
+ // NYI
+ (void)index;
+ (void)ti;
+ return NNFW_STATUS_ERROR;
+}
+
+NNFW_STATUS nnfw_session::train_set_input(uint32_t index, const void *input,
+ const nnfw_tensorinfo *input_tensorinfo)
+{
+ if (input == nullptr)
+ {
+ std::cerr << "Error during nnfw_session::train_set_input : input buffer is null" << std::endl;
+ return NNFW_STATUS_UNEXPECTED_NULL;
+ }
+
+ if (!isStatePreparedOrFinishedTraining())
+ {
+ std::cerr << "Error during nnfw_session::train_set_input : invalid state" << std::endl;
+ return NNFW_STATUS_INVALID_STATE;
+ }
+
+ if (index >= getInputSize())
+ {
+ std::cerr << "Error during nnfw_session::train_set_input : index is out of range" << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+
+ try
+ {
+ auto ind = onert::ir::IOIndex(index);
+ auto size = _execution->getInputTotalSize(ind);
+ if (input_tensorinfo && getBufSize(input_tensorinfo) != size)
+ {
+ std::cerr
+ << "Error during nnfw_session::train_set_input : not supporeted to change tensorinfo"
+ << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+
+ _execution->setInput(ind, input, size);
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Error during nnfw_session::train_set_input : " << e.what() << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+
+ return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::train_set_expected(uint32_t index, const void *expected,
+ const nnfw_tensorinfo *expected_tensorinfo)
+{
+ if (expected == nullptr)
+ {
+ std::cerr << "Error during nnfw_session::train_set_expected : expected buffer is null"
+ << std::endl;
+ return NNFW_STATUS_UNEXPECTED_NULL;
+ }
+
+ if (!isStatePreparedOrFinishedTraining())
+ {
+ std::cerr << "Error during nnfw_session::train_set_expected : invalid state" << std::endl;
+ return NNFW_STATUS_INVALID_STATE;
+ }
+
+ if (index >= getOutputSize())
+ {
+ std::cerr << "Error during nnfw_session::train_set_expected : index is out of range"
+ << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+
+ try
+ {
+ auto output_ind = onert::ir::IOIndex(index);
+ auto size = _execution->getOutputTotalSize(output_ind);
+ if (expected_tensorinfo && getBufSize(expected_tensorinfo) != size)
+ {
+ std::cerr << "Error during nnfw_session::train_set_expected : invalid tensorinfo"
+ << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+
+ // NOTE Find the loss input index
+ // Input is added as many as the number of outputs.
+ // The loss index is calculated from the value obtained by subtracting the
+ // total output(added loss input) from the total input size.
+ auto input_index = getInputSize() - getOutputSize() + index;
+ auto input_ind = onert::ir::IOIndex(input_index);
+ _execution->setInput(input_ind, expected, size);
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Error during nnfw_session::train_set_expected : " << e.what() << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+
+ return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::train_run(bool update_weights)
+{
+ if (!isStatePreparedOrFinishedTraining())
+ {
+ std::cerr << "Error during nnfw_session::train_run : invalid state" << std::endl;
+ return NNFW_STATUS_INVALID_STATE;
+ }
+
+ try
+ {
+ if (update_weights)
+ {
+ _execution->train(_training_step++);
+ }
+ else
+ _execution->execute();
+ }
+ catch (const onert::InsufficientBufferSizeException &e)
+ {
+ // Currently insufficient buffer always means output buffer.
+ std::cerr << "Error during nnfw_session::train_run : " << e.what() << std::endl;
+ return NNFW_STATUS_INSUFFICIENT_OUTPUT_SIZE;
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Error during nnfw_session::train_run : " << e.what() << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+
+ _state = State::FINISHED_TRAINING;
+ return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::train_get_loss(uint32_t index, float *loss)
+{
+ if (loss == nullptr)
+ {
+ std::cerr << "Error during nnfw_session::train_get_loss : loss is null" << std::endl;
+ return NNFW_STATUS_UNEXPECTED_NULL;
+ }
+
+ if (!isStateFinishedTraining())
+ {
+ std::cerr << "Error during nnfw_session::train_get_loss : invalid state" << std::endl;
+ return NNFW_STATUS_INVALID_STATE;
+ }
+
+ if (index >= getOutputSize())
+ {
+ std::cerr << "Error during nnfw_session::train_get_loss : index is out of range" << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+
+ try
+ {
+ auto ind = onert::ir::IOIndex(index);
+ *loss = _execution->getLoss(ind);
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Error during nnfw_session::train_get_loss : " << e.what() << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+
+ return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::train_export_circle(const char *path)
+{
+ if (path == nullptr)
+ {
+ std::cerr << "Error during nnfw_session::train_export_circle : path is null" << std::endl;
+ return NNFW_STATUS_UNEXPECTED_NULL;
+ }
+
+ // Check training mode is enabled
+ if (!isStateFinishedTraining())
+ {
+ std::cerr << "Error during nnfw_session::train_export_circle : invalid state" << std::endl;
+ return NNFW_STATUS_INVALID_STATE;
+ }
+
+ // NYI
+ return NNFW_STATUS_ERROR;
+}
+
+bool nnfw_session::isStatePreparedTraining()
+{
+ if (_state == State::PREPARED_TRAINING)
+ {
+ assert(_nnpkg == nullptr);
+ assert(!_coptions.empty());
+ assert(_execution != nullptr);
+ return true;
+ }
+ else
+ return false;
+}
+
+bool nnfw_session::isStateFinishedTraining()
+{
+ if (_state == State::FINISHED_TRAINING)
+ {
+ assert(_nnpkg == nullptr);
+ assert(!_coptions.empty());
+ assert(_execution != nullptr);
+ return true;
+ }
+ else
+ return false;
+}
+
+bool nnfw_session::isStatePreparedOrFinishedTraining()
+{
+ return isStatePreparedTraining() || isStateFinishedTraining();
+}
+
+#endif // ONERT_TRAIN
+
+NNFW_STATUS nnfw_session::set_quantization_type(NNFW_QUANTIZE_TYPE qtype)
+{
+ try
+ {
+ if (!isStateModelLoaded())
+ {
+ std::cerr << "invalid state" << std::endl;
+ return NNFW_STATUS_INVALID_STATE;
+ }
+
+ bool is_q16 = false;
+ switch (qtype)
+ {
+ case NNFW_QUANTIZE_TYPE_U8_ASYM:
+ break;
+ case NNFW_QUANTIZE_TYPE_I16_SYM:
+ is_q16 = true;
+ break;
+ default:
+ return NNFW_STATUS_INVALID_STATE;
+ }
+ _quant_manager->quantizeType(is_q16);
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Error during nnfw_session::set_quantization_type : " << e.what() << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+
+ return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::set_quantized_model_path(const char *path)
+{
+ try
+ {
+ if (!isStateModelLoaded())
+ {
+ std::cerr << "invalid state" << std::endl;
+ return NNFW_STATUS_INVALID_STATE;
+ }
+
+ _quant_manager->exportModelPath(std::string(path));
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Error during nnfw_session::set_quantized_model_path : " << e.what() << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+
+ return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::quantize()
+{
+ try
+ {
+ if (!isStateModelLoaded())
+ {
+ std::cerr << "invalid state" << std::endl;
+ return NNFW_STATUS_INVALID_STATE;
+ }
+
+ auto result = _quant_manager->quantize();
+ if (!result)
+ return NNFW_STATUS_INVALID_STATE;
+
+ // Replace model
+ // TODO Support buffer replace, not file reload
+ auto model = loadModel(_quant_manager->exportModelPath(), "circle");
+ if (model == nullptr)
+ return NNFW_STATUS_ERROR;
+ _nnpkg->replaceModel(std::move(model));
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Error during nnfw_session::quantize : " << e.what() << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+
+ return NNFW_STATUS_NO_ERROR;
+}
diff --git a/runtime/onert/api/src/nnfw_api_internal.h b/runtime/onert/api/src/nnfw_api_internal.h
index 8e2c2fba6..62791765e 100644
--- a/runtime/onert/api/src/nnfw_api_internal.h
+++ b/runtime/onert/api/src/nnfw_api_internal.h
@@ -39,7 +39,7 @@ class Execution;
} // namespace exec
namespace ir
{
-class Graph;
+struct IGraph;
class Model;
class NNPkg;
} // namespace ir
@@ -48,6 +48,10 @@ namespace compiler
struct CompilerArtifact;
class CompilerOptions;
} // namespace compiler
+namespace odc
+{
+class QuantizeManager;
+} // namespace odc
} // namespace onert
struct nnfw_session
@@ -90,11 +94,13 @@ private:
*/
enum class State
{
- INITIALIZED, //< Session is initialized and nothing has done to it
- MODEL_LOADED, //< Model is loaded
- PREPARED, //< Prepared(compiled) for execution
- RUNNING, //< Execution is in progress (only for asynchronous execution)
- FINISHED_RUN //< Executed at least once
+ INITIALIZED, //< Session is initialized and nothing has done to it
+ MODEL_LOADED, //< Model is loaded
+ PREPARED, //< Prepared(compiled) for execution
+ RUNNING, //< Execution is in progress (only for asynchronous execution)
+ FINISHED_RUN, //< Executed at least once
+ PREPARED_TRAINING, //< Prepared for training
+ FINISHED_TRAINING //< Trained at least once
};
public:
@@ -160,8 +166,25 @@ public:
*/
NNFW_STATUS set_backends_per_operation(const char *backend_settings);
+#ifdef ONERT_TRAIN
+ NNFW_STATUS train_prepare(const nnfw_train_info *info);
+ NNFW_STATUS train_input_tensorinfo(uint32_t index, nnfw_tensorinfo *ti);
+ NNFW_STATUS train_expected_tensorinfo(uint32_t index, nnfw_tensorinfo *ti);
+ NNFW_STATUS train_set_input(uint32_t index, const void *input,
+ const nnfw_tensorinfo *input_tensorinfo);
+ NNFW_STATUS train_set_expected(uint32_t index, const void *expected,
+ const nnfw_tensorinfo *expected_tensorinfo);
+ NNFW_STATUS train_run(bool update_weights);
+ NNFW_STATUS train_get_loss(uint32_t index, float *loss);
+ NNFW_STATUS train_export_circle(const char *path);
+#endif // ONERT_TRAIN
+
+ NNFW_STATUS set_quantization_type(NNFW_QUANTIZE_TYPE qtype);
+ NNFW_STATUS set_quantized_model_path(const char *path);
+ NNFW_STATUS quantize();
+
private:
- const onert::ir::Graph *primary_subgraph();
+ const onert::ir::IGraph *primary_subgraph();
uint32_t getInputSize();
uint32_t getOutputSize();
@@ -171,6 +194,11 @@ private:
bool isStateRunning();
bool isStateFinishedRun();
bool isStatePreparedOrFinishedRun();
+#ifdef ONERT_TRAIN
+ bool isStatePreparedTraining();
+ bool isStateFinishedTraining();
+ bool isStatePreparedOrFinishedTraining();
+#endif // ONERT_TRAIN
private:
State _state{State::INITIALIZED};
@@ -180,6 +208,10 @@ private:
std::unique_ptr<onert::exec::Execution> _execution;
std::shared_ptr<onert::api::CustomKernelRegistry> _kernel_registry;
std::vector<std::thread> _threads;
+#ifdef ONERT_TRAIN
+ uint32_t _training_step{0};
+#endif // ONERT_TRAIN
+ std::unique_ptr<onert::odc::QuantizeManager> _quant_manager;
};
#endif // __API_NNFW_API_INTERNAL_H__
diff --git a/runtime/onert/backend/CMakeLists.txt b/runtime/onert/backend/CMakeLists.txt
index c43160ba7..e6af06afe 100644
--- a/runtime/onert/backend/CMakeLists.txt
+++ b/runtime/onert/backend/CMakeLists.txt
@@ -5,6 +5,7 @@ add_subdirectory(cl_common)
add_subdirectory(acl_common)
# Backends
+set(LIB_ONERT_BACKEND_CPU onert_backend_cpu)
add_subdirectory(cpu)
add_subdirectory(acl_cl)
add_subdirectory(acl_neon)
@@ -12,3 +13,9 @@ add_subdirectory(ruy)
add_subdirectory(gpu_cl)
add_subdirectory(xnnpack)
add_subdirectory(trix)
+
+# Backend to train
+if(ENABLE_ONERT_TRAIN)
+ add_subdirectory(train)
+endif(ENABLE_ONERT_TRAIN)
+
diff --git a/runtime/onert/backend/acl_cl/Config.cc b/runtime/onert/backend/acl_cl/Config.cc
index c10fdc1fe..4d12d60b3 100644
--- a/runtime/onert/backend/acl_cl/Config.cc
+++ b/runtime/onert/backend/acl_cl/Config.cc
@@ -47,7 +47,7 @@ bool Config::initialize()
return true;
}
-ir::Layout Config::supportLayout(const ir::Operation &, ir::Layout frontend_layout)
+ir::Layout Config::supportLayout(const ir::IOperation &, ir::Layout frontend_layout)
{
const std::string acl_layout_str = util::getConfigString(util::config::ACL_LAYOUT);
if (acl_layout_str == "NHWC")
diff --git a/runtime/onert/backend/acl_cl/Config.h b/runtime/onert/backend/acl_cl/Config.h
index f71e81b6a..1fa1aeb00 100644
--- a/runtime/onert/backend/acl_cl/Config.h
+++ b/runtime/onert/backend/acl_cl/Config.h
@@ -35,7 +35,7 @@ public:
std::string id() override { return "acl_cl"; }
bool initialize() override;
bool supportPermutation() override { return true; }
- ir::Layout supportLayout(const ir::Operation &node, ir::Layout frontend_layout) override;
+ ir::Layout supportLayout(const ir::IOperation &node, ir::Layout frontend_layout) override;
bool supportDynamicTensor() override { return false; }
bool supportFP16() override { return true; }
void sync() const override { arm_compute::CLScheduler::get().sync(); }
diff --git a/runtime/onert/backend/acl_cl/KernelGenerator.cc b/runtime/onert/backend/acl_cl/KernelGenerator.cc
index 5b0ec92b7..dcf31858e 100644
--- a/runtime/onert/backend/acl_cl/KernelGenerator.cc
+++ b/runtime/onert/backend/acl_cl/KernelGenerator.cc
@@ -82,7 +82,7 @@ void KernelGenerator::visit(const ir::operation::BatchToSpaceND &node)
}
auto crops = _ctx.at(crops_index).asVector<int32_t>();
- for (auto crop : crops)
+ for (auto &&crop : crops)
{
if (crop != 0)
{
diff --git a/runtime/onert/backend/acl_cl/Optimizer.cc b/runtime/onert/backend/acl_cl/Optimizer.cc
index a9ce888ee..0f779f483 100644
--- a/runtime/onert/backend/acl_cl/Optimizer.cc
+++ b/runtime/onert/backend/acl_cl/Optimizer.cc
@@ -44,7 +44,7 @@ void Optimizer::optimize()
acl_common::AclSubTensorAnalyzer sa{*_context->graph()};
sa.setUsePadding();
_context->graph()->operations().iterate(
- [&](const ir::OperationIndex &, const ir::Operation &op) {
+ [&](const ir::OperationIndex &, const ir::IOperation &op) {
sa.setLayout(_context->graph()->layout());
op.accept(sa);
});
diff --git a/runtime/onert/backend/acl_common/AclTensorManager.h b/runtime/onert/backend/acl_common/AclTensorManager.h
index 268cec201..41a89fbf2 100644
--- a/runtime/onert/backend/acl_common/AclTensorManager.h
+++ b/runtime/onert/backend/acl_common/AclTensorManager.h
@@ -261,13 +261,13 @@ template <typename T_ITensor, typename T_Tensor, typename T_SubTensor>
void AclTensorManager<T_ITensor, T_Tensor, T_SubTensor>::iterate(
const std::function<void(const ir::OperandIndex &)> &fn)
{
- for (auto it : _nonconst_mgr->tensors())
+ for (auto &&it : _nonconst_mgr->tensors())
fn(it.first);
- for (auto it : _nonconst_mgr->subtensors())
+ for (auto &&it : _nonconst_mgr->subtensors())
fn(it.first);
- for (auto it : _const_mgr->tensors())
+ for (auto &&it : _const_mgr->tensors())
fn(it.first);
}
diff --git a/runtime/onert/backend/acl_neon/Config.cc b/runtime/onert/backend/acl_neon/Config.cc
index 4e78efd2d..3f1758c80 100644
--- a/runtime/onert/backend/acl_neon/Config.cc
+++ b/runtime/onert/backend/acl_neon/Config.cc
@@ -27,7 +27,7 @@ namespace acl_neon
bool Config::initialize() { return true; }
-ir::Layout Config::supportLayout(const ir::Operation &, ir::Layout frontend_layout)
+ir::Layout Config::supportLayout(const ir::IOperation &, ir::Layout frontend_layout)
{
const std::string acl_layout_str = util::getConfigString(util::config::ACL_LAYOUT);
if (acl_layout_str == "NHWC")
diff --git a/runtime/onert/backend/acl_neon/Config.h b/runtime/onert/backend/acl_neon/Config.h
index 089d9479a..ffd9b21e3 100644
--- a/runtime/onert/backend/acl_neon/Config.h
+++ b/runtime/onert/backend/acl_neon/Config.h
@@ -33,7 +33,7 @@ class Config : public IConfig
public:
std::string id() override { return "acl_neon"; }
bool initialize() override;
- ir::Layout supportLayout(const ir::Operation &node, ir::Layout frontend_layout) override;
+ ir::Layout supportLayout(const ir::IOperation &node, ir::Layout frontend_layout) override;
bool supportPermutation() override { return true; }
bool supportDynamicTensor() override { return false; }
bool supportFP16() override { return false; }
diff --git a/runtime/onert/backend/acl_neon/KernelGenerator.cc b/runtime/onert/backend/acl_neon/KernelGenerator.cc
index 94ea86dcf..e71aa3693 100644
--- a/runtime/onert/backend/acl_neon/KernelGenerator.cc
+++ b/runtime/onert/backend/acl_neon/KernelGenerator.cc
@@ -111,7 +111,7 @@ void KernelGenerator::visit(const ir::operation::BatchToSpaceND &node)
}
auto crops = _ctx.at(crops_index).asVector<int32_t>();
- for (auto crop : crops)
+ for (auto &&crop : crops)
{
if (crop != 0)
{
diff --git a/runtime/onert/backend/acl_neon/Optimizer.cc b/runtime/onert/backend/acl_neon/Optimizer.cc
index 283edd174..f207ca8cb 100644
--- a/runtime/onert/backend/acl_neon/Optimizer.cc
+++ b/runtime/onert/backend/acl_neon/Optimizer.cc
@@ -44,7 +44,7 @@ void Optimizer::optimize()
acl_common::AclSubTensorAnalyzer sa{*_context->graph()};
sa.setUsePadding();
_context->graph()->operations().iterate(
- [&](const ir::OperationIndex &, const ir::Operation &op) {
+ [&](const ir::OperationIndex &, const ir::IOperation &op) {
sa.setLayout(_context->graph()->layout());
op.accept(sa);
});
diff --git a/runtime/onert/backend/cl_common/include/cl_common/BackendContext.h b/runtime/onert/backend/cl_common/include/cl_common/BackendContext.h
index 5536d2780..76d403949 100644
--- a/runtime/onert/backend/cl_common/include/cl_common/BackendContext.h
+++ b/runtime/onert/backend/cl_common/include/cl_common/BackendContext.h
@@ -51,7 +51,7 @@ public:
FunctionMap ret;
// kernel_gen
- for (auto op_ind : _data.op_order)
+ for (auto &&op_ind : _data.op_order)
{
auto fn_seq = kernel_gen->generate(op_ind);
ret.emplace_back(op_ind, std::move(fn_seq));
@@ -80,7 +80,7 @@ public:
protected:
void initConsts()
{
- _data.graph->operations().iterate([&](const ir::OperationIndex &, const ir::Operation &op) {
+ _data.graph->operations().iterate([&](const ir::OperationIndex &, const ir::IOperation &op) {
constant_initializer->setLayout(graph()->layout());
op.accept(*constant_initializer);
});
@@ -144,7 +144,7 @@ protected:
// 1. Scan DEF of outputs. If the DEF, allocate it
// 2. Scan DEF of inputs. If variable tensor, allocate it
// 3. Scan USE of inputs. Decrease the USE and deallocate if the USE is 0
- for (const auto op_ind : _data.op_order)
+ for (const auto &op_ind : _data.op_order)
{
const auto &op = graph()->operations().at(op_ind);
auto op_inputs = op.getInputs() | ir::Remove::DUPLICATED | ir::Remove::UNDEFINED;
diff --git a/runtime/onert/backend/cpu/BackendContext.cc b/runtime/onert/backend/cpu/BackendContext.cc
index da48a785d..45de6b972 100644
--- a/runtime/onert/backend/cpu/BackendContext.cc
+++ b/runtime/onert/backend/cpu/BackendContext.cc
@@ -37,7 +37,7 @@ FunctionMap BackendContext::genKernels()
{
FunctionMap ret;
- for (auto op_ind : _data.op_order)
+ for (auto &&op_ind : _data.op_order)
{
auto fn_seq = kernel_gen->generate(op_ind);
ret.emplace_back(op_ind, std::move(fn_seq));
diff --git a/runtime/onert/backend/cpu/CMakeLists.txt b/runtime/onert/backend/cpu/CMakeLists.txt
index 99643b983..1383263e7 100644
--- a/runtime/onert/backend/cpu/CMakeLists.txt
+++ b/runtime/onert/backend/cpu/CMakeLists.txt
@@ -1,11 +1,10 @@
-set(LIB_ONERT_BACKEND_CPU onert_backend_cpu)
-
nnfw_find_package(Ruy REQUIRED)
file(GLOB_RECURSE SOURCES "*.cc")
add_library(${LIB_ONERT_BACKEND_CPU} SHARED ${SOURCES})
+target_include_directories(${LIB_ONERT_BACKEND_CPU} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(${LIB_ONERT_BACKEND_CPU} PRIVATE nnfw_lib_cker nnfw_lib_misc)
target_link_libraries(${LIB_ONERT_BACKEND_CPU} PRIVATE onert_core)
target_link_libraries(${LIB_ONERT_BACKEND_CPU} PRIVATE nnfw_common)
@@ -15,6 +14,7 @@ target_link_libraries(${LIB_ONERT_BACKEND_CPU} INTERFACE ruy_instrumentation)
target_link_libraries(${LIB_ONERT_BACKEND_CPU} PRIVATE ndarray)
set_target_properties(${LIB_ONERT_BACKEND_CPU} PROPERTIES OUTPUT_NAME backend_cpu)
+set_target_properties(${LIB_ONERT_BACKEND_CPU} PROPERTIES POSITION_INDEPENDENT_CODE ON)
if(CMAKE_BUILD_TYPE_LC STREQUAL "release")
add_custom_command(TARGET ${LIB_ONERT_BACKEND_CPU} POST_BUILD
diff --git a/runtime/onert/backend/cpu/Config.cc b/runtime/onert/backend/cpu/Config.cc
index 3ace47f5d..f80c2caf1 100644
--- a/runtime/onert/backend/cpu/Config.cc
+++ b/runtime/onert/backend/cpu/Config.cc
@@ -25,7 +25,7 @@ namespace cpu
bool Config::initialize() { return true; }
-ir::Layout Config::supportLayout(const ir::Operation &, ir::Layout) { return ir::Layout::NHWC; }
+ir::Layout Config::supportLayout(const ir::IOperation &, ir::Layout) { return ir::Layout::NHWC; }
} // namespace cpu
} // namespace backend
diff --git a/runtime/onert/backend/cpu/Config.h b/runtime/onert/backend/cpu/Config.h
index 37e49581a..841a839d1 100644
--- a/runtime/onert/backend/cpu/Config.h
+++ b/runtime/onert/backend/cpu/Config.h
@@ -33,7 +33,7 @@ class Config : public IConfig
public:
std::string id() override { return "cpu"; }
bool initialize() override;
- ir::Layout supportLayout(const ir::Operation &node, ir::Layout frontend_layout) override;
+ ir::Layout supportLayout(const ir::IOperation &node, ir::Layout frontend_layout) override;
bool supportPermutation() override { return true; }
bool supportDynamicTensor() override { return true; }
bool supportFP16() override { return false; }
diff --git a/runtime/onert/backend/cpu/KernelGenerator.cc b/runtime/onert/backend/cpu/KernelGenerator.cc
index 896883bc3..c927bf5d4 100644
--- a/runtime/onert/backend/cpu/KernelGenerator.cc
+++ b/runtime/onert/backend/cpu/KernelGenerator.cc
@@ -257,7 +257,7 @@ std::unique_ptr<exec::FunctionSequence> KernelGenerator::generate(ir::OperationI
assert(_return_fn); // _return_fn must have been generated
ret->append(std::move(_return_fn));
- for (auto ind : (op.getInputs() | ir::Remove::UNDEFINED) + op.getOutputs())
+ for (auto &&ind : (op.getInputs() | ir::Remove::UNDEFINED) + op.getOutputs())
{
auto portable_tensor = _tensor_reg->getPortableTensor(ind);
if (portable_tensor)
diff --git a/runtime/onert/backend/cpu/ops/ConvolutionLayer.cc b/runtime/onert/backend/cpu/ops/ConvolutionLayer.cc
index 4672fe406..62e8ae4ba 100644
--- a/runtime/onert/backend/cpu/ops/ConvolutionLayer.cc
+++ b/runtime/onert/backend/cpu/ops/ConvolutionLayer.cc
@@ -16,6 +16,7 @@
#include "ConvolutionLayer.h"
#include "OperationUtils.h"
+#include "cker/PortableTensorUtils.h"
#include "../Tensor.h"
#include "ir/Padding.h"
@@ -34,7 +35,7 @@ ConvolutionLayer::ConvolutionLayer()
_paddingType(ir::PaddingType::EXPLICIT), _paddingLeft(0), _paddingTop(0), _paddingRight(0),
_paddingBottom(0), _strideWidth(0), _strideHeight(0), _dilationWidthFactor(1),
_dilationHeightFactor(1), _activation(ir::Activation::NONE),
- _conv_kernel(new nnfw::cker::Conv()), _prepare(false)
+ _conv_kernel(new nnfw::cker::Conv()), _prepare(false), _is_hybrid(false)
{
// DO NOTHING
}
@@ -151,6 +152,47 @@ void ConvolutionLayer::convQ8i()
reinterpret_cast<int8_t *>(_output->buffer()));
}
+void ConvolutionLayer::convQ8iHybridPerChannel()
+{
+ float output_activation_min = 0;
+ float output_activation_max = 0;
+ CalculateActivationRange(_activation, &output_activation_min, &output_activation_max);
+
+ const int batch_size = getShape(_input).Dims(0);
+ if (batch_size == 0)
+ throw std::runtime_error{"Convolution input batch_size = 0"};
+ auto input_shape = getShape(_input);
+ const int input_size = input_shape.FlatSize() / batch_size;
+
+ auto input_quantized_ptr = _hybrid_arena->input_quantized.data();
+ auto input_scaling_factors_ptr = _hybrid_arena->input_scaling_factors.data();
+ auto input_offsets_ptr = _hybrid_arena->input_offsets.data();
+ for (int b = 0; b < batch_size; ++b)
+ {
+ const int offset = b * input_size;
+ nnfw::cker::PortableAsymmetricQuantizeFloats(
+ reinterpret_cast<const float *>(_input->buffer()) + offset, input_size,
+ input_quantized_ptr + offset, &input_scaling_factors_ptr[b], &input_offsets_ptr[b]);
+ }
+ nnfw::cker::ConvParams op_params;
+ op_params.padding_type = getPaddingType(_paddingType);
+ op_params.padding_values.width = _paddingLeft;
+ op_params.padding_values.height = _paddingTop;
+ op_params.stride_width = _strideWidth;
+ op_params.stride_height = _strideHeight;
+ op_params.dilation_width_factor = _dilationWidthFactor;
+ op_params.dilation_height_factor = _dilationHeightFactor;
+ op_params.float_activation_min = output_activation_min;
+ op_params.float_activation_max = output_activation_max;
+
+ const auto *filter_per_channel_scales = _kernel->data_scales().data();
+ nnfw::cker::reference::HybridConvPerChannel(
+ op_params, input_scaling_factors_ptr, getShape(_input), input_quantized_ptr, getShape(_kernel),
+ reinterpret_cast<const int8_t *>(_kernel->buffer()), getShape(_bias),
+ reinterpret_cast<const float *>(_bias->buffer()), getShape(_output),
+ reinterpret_cast<float *>(_output->buffer()), filter_per_channel_scales, input_offsets_ptr);
+}
+
void ConvolutionLayer::configure(const IPortableTensor *input, const IPortableTensor *kernel,
const IPortableTensor *bias, const ir::PaddingType paddingType,
const uint32_t paddingLeft, const uint32_t paddingRight,
@@ -174,12 +216,13 @@ void ConvolutionLayer::configure(const IPortableTensor *input, const IPortableTe
_dilationHeightFactor = dilationHeightFactor;
_activation = activation;
_output = output;
+ _is_hybrid = _input->data_type() == OperandType::FLOAT32 &&
+ _kernel->data_type() == OperandType::QUANT_INT8_SYMM;
}
void ConvolutionLayer::run()
{
prepare();
-
if (_input->is_dynamic() || _kernel->is_dynamic())
{
const auto ifm_shape = _input->getShape().asFeature(_input->layout());
@@ -209,7 +252,11 @@ void ConvolutionLayer::run()
_paddingTop = padding.top;
_paddingBottom = padding.bottom;
}
- if (_input->data_type() == OperandType::FLOAT32)
+ if (_is_hybrid)
+ {
+ convQ8iHybridPerChannel();
+ }
+ else if (_input->data_type() == OperandType::FLOAT32)
{
convFloat32();
}
@@ -236,6 +283,27 @@ void ConvolutionLayer::prepare()
if (_prepare)
return;
+ if (_is_hybrid)
+ {
+ // ensure weight is per-channel quantized.
+ int32_t kernel_output_channel = getShape(_kernel).Dims(0);
+ // zero_points comes from flatbuffer vector. Its size is within uint32_t range.
+ size_t kernel_zerop_cnt = _kernel->data_scales().size();
+ // promote to int64_t to compare int32_t and uint32_t
+ if ((int64_t)kernel_output_channel != (int64_t)kernel_zerop_cnt)
+ throw std::runtime_error{"Conv2D hybrid supports only per-channel quantized weight."};
+
+ // allocate memory for activation quantization.
+ // - quantized values (int8_t type and same shape of original input)
+ // - quantization params (= scale/zeropoint for each input)
+ auto input_shape = getShape(_input);
+ const int batch_size = input_shape.Dims(0);
+ const int input_size = input_shape.FlatSize() / batch_size;
+ _hybrid_arena = std::make_unique<nnfw::cker::ConvHybridTempArena>(batch_size, input_size);
+ _prepare = true;
+ return;
+ }
+
nnfw::cker::Conv &kernel = *_conv_kernel;
if (_input->data_type() == OperandType::FLOAT32 && _kernel->is_constant())
{
diff --git a/runtime/onert/backend/cpu/ops/ConvolutionLayer.h b/runtime/onert/backend/cpu/ops/ConvolutionLayer.h
index 9f5253c8e..5e1bd0b08 100644
--- a/runtime/onert/backend/cpu/ops/ConvolutionLayer.h
+++ b/runtime/onert/backend/cpu/ops/ConvolutionLayer.h
@@ -29,7 +29,9 @@ namespace nnfw
namespace cker
{
class Conv;
-}
+struct ConvHybridTempArena;
+class Shape;
+} // namespace cker
} // namespace nnfw
namespace onert
@@ -48,13 +50,6 @@ public:
~ConvolutionLayer();
public:
- void convFloat32();
-
- void convQ8uPerTensor();
- void convQ8uPerChannel();
-
- void convQ8i();
-
void configure(const IPortableTensor *input, const IPortableTensor *kernel,
const IPortableTensor *bias, ir::PaddingType _paddingType,
const uint32_t paddingLeft, const uint32_t paddingRight, const uint32_t paddingTop,
@@ -62,10 +57,15 @@ public:
const uint32_t strideHeight, const uint32_t dilationWidthFactor,
const uint32_t dilationHeightFactor, const ir::Activation activation,
IPortableTensor *output);
-
+ void prepare() override;
void run() override;
- void prepare() override;
+private:
+ void convFloat32();
+ void convQ8uPerTensor();
+ void convQ8uPerChannel();
+ void convQ8i();
+ void convQ8iHybridPerChannel();
private:
const IPortableTensor *_input;
@@ -87,8 +87,10 @@ private:
ir::Activation _activation;
std::unique_ptr<nnfw::cker::Conv> _conv_kernel;
+ std::unique_ptr<nnfw::cker::ConvHybridTempArena> _hybrid_arena;
bool _prepare;
+ bool _is_hybrid;
};
} // namespace ops
diff --git a/runtime/onert/backend/cpu/ops/DepthwiseConvolutionLayer.cc b/runtime/onert/backend/cpu/ops/DepthwiseConvolutionLayer.cc
index 8a48497d5..9e6de17f2 100644
--- a/runtime/onert/backend/cpu/ops/DepthwiseConvolutionLayer.cc
+++ b/runtime/onert/backend/cpu/ops/DepthwiseConvolutionLayer.cc
@@ -16,6 +16,7 @@
#include "DepthwiseConvolutionLayer.h"
+#include "cker/PortableTensorUtils.h"
#include <cker/operation/DepthwiseConv.h>
namespace onert
@@ -147,6 +148,50 @@ void DepthwiseConvolutionLayer::convQ8i()
_external_context->ruy_context());
}
+void DepthwiseConvolutionLayer::convQ8iHybridPerChannel()
+{
+ if (!_prepared)
+ {
+ prepareQ8iHybridPerChannel();
+ _prepared = true;
+ }
+
+ float output_activation_min = 0, output_activation_max = 0;
+ CalculateActivationRange(_activation, &output_activation_min, &output_activation_max);
+
+ auto input_shape = getShape(_input);
+ const int batch_size = input_shape.Dims(0);
+ const int input_size = input_shape.FlatSize() / batch_size;
+
+ auto scaling_factors_ptr = _input_scaling_factors.data();
+ auto input_offsets_ptr = _input_offsets.data();
+
+ for (int b = 0; b < batch_size; ++b)
+ {
+ const int offset = b * input_size;
+ nnfw::cker::PortableAsymmetricQuantizeFloats(getBuffer<float>(_input) + offset, input_size,
+ _input_quantized.data() + offset,
+ &scaling_factors_ptr[b], &input_offsets_ptr[b]);
+ }
+
+ nnfw::cker::DepthwiseConvParams op_params;
+ op_params.padding_values.width = _paddingLeft;
+ op_params.padding_values.height = _paddingTop;
+ op_params.depth_multiplier = _multiplier;
+ op_params.stride_width = _strideWidth;
+ op_params.stride_height = _strideHeight;
+ op_params.dilation_width_factor = _dilationWidth;
+ op_params.dilation_height_factor = _dilationHeight;
+ op_params.float_activation_min = output_activation_min;
+ op_params.float_activation_max = output_activation_max;
+
+ nnfw::cker::reference_integer_ops::DepthwiseConvHybridPerChannel(
+ op_params, _input_scaling_factors.data(), getShape(_input), _input_quantized.data(),
+ getShape(_kernel), getBuffer<int8_t>(_kernel), getShape(_bias), getBuffer<float>(_bias),
+ getShape(_output), getBuffer<float>(_output), _kernel->data_scales().data(),
+ _input_offsets.data());
+}
+
void DepthwiseConvolutionLayer::prepareQ8i()
{
GetQuantizedConvolutionMultipliersAndShifts(
@@ -163,6 +208,31 @@ void DepthwiseConvolutionLayer::prepareQ8uPerChannel()
_per_channel_output_shift);
}
+void DepthwiseConvolutionLayer::prepareQ8iHybridPerChannel()
+{
+ // allocate memory for activation quantization.
+ // - quantized values (int8_t type and same shape of original input)
+ // - quantization params (= scale/zeropoint for each input)
+ auto input_shape = getShape(_input);
+ const int batch_size = input_shape.Dims(0);
+ const int input_size = input_shape.FlatSize() / batch_size;
+ _input_quantized.resize(input_size);
+ // TODO: Optimize the case of batch_size = 1
+ _input_scaling_factors.resize(batch_size);
+ _input_offsets.resize(batch_size);
+}
+
+void DepthwiseConvolutionLayer::ensureQ8iHybridPerChannel()
+{
+ // ensure weight is per-channel quantized.
+ int32_t kernel_input_channel = getShape(_kernel).Dims(3);
+ // zero_points comes from flatbuffer vector. Its size is within uint32_t range.
+ size_t kernel_zerop_cnt = _kernel->data_scales().size();
+ // promote to int64_t to compare int32_t and uint32_t
+ if ((int64_t)kernel_input_channel != (int64_t)kernel_zerop_cnt)
+ throw std::runtime_error{"DConv2D hybrid supports only per-channel quantized weight."};
+}
+
void DepthwiseConvolutionLayer::configure(
const IPortableTensor *input, const IPortableTensor *kernel, const IPortableTensor *bias,
const uint32_t paddingLeft, const uint32_t paddingRight, const uint32_t paddingTop,
@@ -186,8 +256,16 @@ void DepthwiseConvolutionLayer::configure(
_activation = activation;
_output = output;
_external_context = external_context;
+ _is_hybrid = _input->data_type() == OperandType::FLOAT32 &&
+ _kernel->data_type() == OperandType::QUANT_INT8_SYMM;
- if (_input->data_type() == OperandType::QUANT_INT8_ASYMM)
+ if (_is_hybrid)
+ {
+ ensureQ8iHybridPerChannel();
+ prepareQ8iHybridPerChannel();
+ _prepared = true;
+ }
+ else if (_input->data_type() == OperandType::QUANT_INT8_ASYMM)
{
if (_kernel->is_constant() && !_input->is_dynamic() && !_output->is_dynamic())
{
@@ -209,7 +287,11 @@ void DepthwiseConvolutionLayer::configure(
void DepthwiseConvolutionLayer::run()
{
- if (_input->data_type() == OperandType::FLOAT32)
+ if (_is_hybrid)
+ {
+ convQ8iHybridPerChannel();
+ }
+ else if (_input->data_type() == OperandType::FLOAT32)
{
convFloat32();
}
diff --git a/runtime/onert/backend/cpu/ops/DepthwiseConvolutionLayer.h b/runtime/onert/backend/cpu/ops/DepthwiseConvolutionLayer.h
index 5c910109a..5721f8796 100644
--- a/runtime/onert/backend/cpu/ops/DepthwiseConvolutionLayer.h
+++ b/runtime/onert/backend/cpu/ops/DepthwiseConvolutionLayer.h
@@ -44,6 +44,7 @@ public:
void convQ8uPerChannel();
void convQ8i();
+ void convQ8iHybridPerChannel();
void configure(const IPortableTensor *input, const IPortableTensor *kernel,
const IPortableTensor *bias, const uint32_t paddingLeft,
@@ -58,6 +59,8 @@ public:
private:
void prepareQ8i();
void prepareQ8uPerChannel();
+ void prepareQ8iHybridPerChannel();
+ void ensureQ8iHybridPerChannel();
private:
const IPortableTensor *_input{nullptr};
@@ -87,6 +90,12 @@ private:
// Per channel output multiplier and shift.
std::vector<int32_t> _per_channel_output_multiplier;
std::vector<int> _per_channel_output_shift;
+
+ // For hybrid
+ bool _is_hybrid{false};
+ std::vector<int8_t> _input_quantized;
+ std::vector<float> _input_scaling_factors;
+ std::vector<int32_t> _input_offsets;
};
} // namespace ops
diff --git a/runtime/onert/backend/cpu/ops/ElementwiseActivationLayer.h b/runtime/onert/backend/cpu/ops/ElementwiseActivationLayer.h
index 948ab3b57..d8a90148f 100644
--- a/runtime/onert/backend/cpu/ops/ElementwiseActivationLayer.h
+++ b/runtime/onert/backend/cpu/ops/ElementwiseActivationLayer.h
@@ -54,7 +54,7 @@ public:
void EvalUsingLookupTable(const IPortableTensor *input, IPortableTensor *output);
-private:
+protected:
const IPortableTensor *_input;
IPortableTensor *_output;
uint8_t _table[256];
diff --git a/runtime/onert/backend/cpu/ops/FullyConnectedLayer.cc b/runtime/onert/backend/cpu/ops/FullyConnectedLayer.cc
index 6857f7f9f..32cad84cb 100644
--- a/runtime/onert/backend/cpu/ops/FullyConnectedLayer.cc
+++ b/runtime/onert/backend/cpu/ops/FullyConnectedLayer.cc
@@ -43,7 +43,16 @@ FullyConnectedLayer::~FullyConnectedLayer() = default;
void FullyConnectedLayer::fullyConnectedFloat32()
{
nnfw::cker::FullyConnectedParams op_params;
+ float output_activation_min = 0;
+ float output_activation_max = 0;
+ CalculateActivationRange(_activation, &output_activation_min, &output_activation_max);
+
op_params.activation = convertActivationType(_activation);
+ op_params.float_activation_min = output_activation_min;
+ op_params.float_activation_max = output_activation_max;
+ // TODO Set both cachables as false when training
+ op_params.lhs_cacheable = _weights->is_constant();
+ op_params.rhs_cacheable = _input->is_constant();
nnfw::cker::FullyConnected(op_params, getShape(_input), getBuffer<float>(_input),
getShape(_weights), getBuffer<float>(_weights), getShape(_bias),
diff --git a/runtime/onert/backend/cpu/ops/FullyConnectedLayer.h b/runtime/onert/backend/cpu/ops/FullyConnectedLayer.h
index cd12829a0..c56398def 100644
--- a/runtime/onert/backend/cpu/ops/FullyConnectedLayer.h
+++ b/runtime/onert/backend/cpu/ops/FullyConnectedLayer.h
@@ -66,7 +66,7 @@ public:
void prepare() override;
-private:
+protected:
const IPortableTensor *_input;
const IPortableTensor *_weights;
const IPortableTensor *_bias;
diff --git a/runtime/onert/backend/cpu/ops/OperationUtils.cc b/runtime/onert/backend/cpu/ops/OperationUtils.cc
index aa4ef352e..686865af2 100644
--- a/runtime/onert/backend/cpu/ops/OperationUtils.cc
+++ b/runtime/onert/backend/cpu/ops/OperationUtils.cc
@@ -256,7 +256,7 @@ uint32_t sizeOfData(OperandType type, const std::vector<int32_t> &dimensions)
break;
}
- for (auto d : dimensions)
+ for (auto &&d : dimensions)
{
assert(d >= 0);
size *= static_cast<uint32_t>(d);
diff --git a/runtime/onert/backend/gpu_cl/BackendContext.cc b/runtime/onert/backend/gpu_cl/BackendContext.cc
index b09319d98..9d4577013 100644
--- a/runtime/onert/backend/gpu_cl/BackendContext.cc
+++ b/runtime/onert/backend/gpu_cl/BackendContext.cc
@@ -90,7 +90,7 @@ FunctionMap BackendContext::genKernels()
{
FunctionMap fn_map;
- for (auto op_ind : _data.op_order)
+ for (auto &&op_ind : _data.op_order)
{
auto fn_seq = kernel_gen->generate(op_ind);
fn_map.emplace_back(op_ind, std::move(fn_seq));
diff --git a/runtime/onert/backend/gpu_cl/Config.cc b/runtime/onert/backend/gpu_cl/Config.cc
index 9959a471b..9b314d679 100644
--- a/runtime/onert/backend/gpu_cl/Config.cc
+++ b/runtime/onert/backend/gpu_cl/Config.cc
@@ -41,7 +41,7 @@ bool Config::initialize()
}
}
-ir::Layout Config::supportLayout(const ir::Operation &, ir::Layout) { return ir::Layout::NHWC; }
+ir::Layout Config::supportLayout(const ir::IOperation &, ir::Layout) { return ir::Layout::NHWC; }
} // namespace gpu_cl
} // namespace backend
diff --git a/runtime/onert/backend/gpu_cl/Config.h b/runtime/onert/backend/gpu_cl/Config.h
index f8f94aaf4..980eb228b 100644
--- a/runtime/onert/backend/gpu_cl/Config.h
+++ b/runtime/onert/backend/gpu_cl/Config.h
@@ -36,7 +36,7 @@ public:
public:
std::string id() override { return "gpu_cl"; }
bool initialize() override;
- ir::Layout supportLayout(const ir::Operation &node, ir::Layout frontend_layout) override;
+ ir::Layout supportLayout(const ir::IOperation &node, ir::Layout frontend_layout) override;
bool supportPermutation() override { return true; }
bool supportDynamicTensor() override { return false; }
bool supportFP16() override { return true; }
diff --git a/runtime/onert/backend/gpu_cl/TensorManager.cc b/runtime/onert/backend/gpu_cl/TensorManager.cc
index 02e26ed91..02e3441ca 100644
--- a/runtime/onert/backend/gpu_cl/TensorManager.cc
+++ b/runtime/onert/backend/gpu_cl/TensorManager.cc
@@ -103,10 +103,10 @@ ir::OperandIndexMap<std::shared_ptr<operand::CLTensor>> &TensorManager::nonconst
void TensorManager::iterate(const std::function<void(const ir::OperandIndex &)> &fn)
{
- for (auto it : _nonconst_mgr->tensors())
+ for (auto &&it : _nonconst_mgr->tensors())
fn(it.first);
- for (auto it : _const_mgr->tensors())
+ for (auto &&it : _const_mgr->tensors())
fn(it.first);
}
diff --git a/runtime/onert/backend/ruy/BackendContext.cc b/runtime/onert/backend/ruy/BackendContext.cc
index 48da91b50..1943f70c7 100644
--- a/runtime/onert/backend/ruy/BackendContext.cc
+++ b/runtime/onert/backend/ruy/BackendContext.cc
@@ -37,7 +37,7 @@ FunctionMap BackendContext::genKernels()
{
FunctionMap ret;
- for (auto op_ind : _data.op_order)
+ for (auto &&op_ind : _data.op_order)
{
auto fn_seq = kernel_gen->generate(op_ind);
ret.emplace_back(op_ind, std::move(fn_seq));
diff --git a/runtime/onert/backend/ruy/Config.cc b/runtime/onert/backend/ruy/Config.cc
index c794f89bf..fbeb2f7f0 100644
--- a/runtime/onert/backend/ruy/Config.cc
+++ b/runtime/onert/backend/ruy/Config.cc
@@ -25,7 +25,7 @@ namespace ruy
bool Config::initialize() { return true; }
-ir::Layout Config::supportLayout(const ir::Operation &, ir::Layout) { return ir::Layout::NHWC; }
+ir::Layout Config::supportLayout(const ir::IOperation &, ir::Layout) { return ir::Layout::NHWC; }
} // namespace ruy
} // namespace backend
diff --git a/runtime/onert/backend/ruy/Config.h b/runtime/onert/backend/ruy/Config.h
index 9160dd5b1..fa6415b14 100644
--- a/runtime/onert/backend/ruy/Config.h
+++ b/runtime/onert/backend/ruy/Config.h
@@ -33,7 +33,7 @@ class Config : public IConfig
public:
std::string id() override { return "ruy"; }
bool initialize() override;
- ir::Layout supportLayout(const ir::Operation &node, ir::Layout frontend_layout) override;
+ ir::Layout supportLayout(const ir::IOperation &node, ir::Layout frontend_layout) override;
bool supportPermutation() override { return true; }
bool supportDynamicTensor() override { return true; }
bool supportFP16() override { return false; }
diff --git a/runtime/onert/backend/ruy/KernelGenerator.cc b/runtime/onert/backend/ruy/KernelGenerator.cc
index b2bbf9bfc..ae7ec28fd 100644
--- a/runtime/onert/backend/ruy/KernelGenerator.cc
+++ b/runtime/onert/backend/ruy/KernelGenerator.cc
@@ -55,7 +55,7 @@ std::unique_ptr<exec::FunctionSequence> KernelGenerator::generate(ir::OperationI
assert(_return_fn); // _return_fn must have been generated
ret->append(std::move(_return_fn));
- for (auto ind : (op.getInputs() | ir::Remove::UNDEFINED) + op.getOutputs())
+ for (auto &&ind : (op.getInputs() | ir::Remove::UNDEFINED) + op.getOutputs())
{
auto portable_tensor = _tensor_reg->getPortableTensor(ind);
if (portable_tensor)
diff --git a/runtime/onert/backend/train/Backend.h b/runtime/onert/backend/train/Backend.h
new file mode 100644
index 000000000..9b8d50a56
--- /dev/null
+++ b/runtime/onert/backend/train/Backend.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_TRAIN_BACKEND_H__
+#define __ONERT_BACKEND_TRAIN_BACKEND_H__
+
+#include "BackendContext.h"
+#include "Config.h"
+#include "KernelGenerator.h"
+
+#include <backend/Backend.h>
+#include <backend/train/ITrainableBackend.h>
+
+#include <memory>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+// TODO Unify TensorBuilder
+// TODO Unify TensorRegistry
+class Backend : public ::onert::backend::Backend, public backend::train::ITrainableBackend
+{
+public:
+ Backend() : _config{std::make_shared<Config>()} {}
+
+ std::shared_ptr<IConfig> config() const override { return _config; }
+
+ std::unique_ptr<onert::backend::BackendContext> newContext(ContextData &&data) const override
+ {
+ return std::make_unique<DummyBackendContext>(this, std::move(data));
+ }
+
+ std::unique_ptr<backend::train::TrainableBackendContext>
+ newContext(backend::train::TrainableContextData &&tdata) const override
+ {
+ const auto &tgraph = *tdata.tgraph;
+ auto tr = std::make_shared<TensorRegistry>();
+ auto tb = std::make_shared<TensorBuilder>(tr, "Bump");
+ auto tdata_ptr = std::make_unique<backend::train::TrainableContextData>(std::move(tdata));
+ auto context = std::make_unique<train::BackendContext>(this, std::move(tdata_ptr), tr, tb);
+
+ context->kernel_gen = std::make_shared<train::KernelGenerator>(
+ tgraph, tr, context->external_context(), context->data()->optimizer);
+ return context;
+ }
+
+private:
+ std::shared_ptr<IConfig> _config;
+};
+
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_BACKEND_H__
diff --git a/runtime/onert/backend/train/BackendContext.cc b/runtime/onert/backend/train/BackendContext.cc
new file mode 100644
index 000000000..3ee9a7233
--- /dev/null
+++ b/runtime/onert/backend/train/BackendContext.cc
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "BackendContext.h"
+
+#include "TensorBuilder.h"
+#include "KernelGenerator.h"
+
+#include <backend/basic/train/TrainableBackendContextHelpers.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+backend::ITensorRegistry *BackendContext::genTensors()
+{
+ return basic::train::genTensors(*this, _tensor_builder);
+}
+
+backend::train::ITensorRegistry *BackendContext::genTrainingTensors()
+{
+ const ir::train::TrainableGraph &tgraph = *trainable_graph();
+ auto tensor_builder = _tensor_builder;
+
+ tgraph.operands().iterate([&](const ir::OperandIndex &ind, const ir::Operand &obj) {
+ if (external_operands().contains(ind))
+ return;
+ // NOTE Assuming there is no layout changes (Always assume NHWC or UNKNOWN)
+ assert(tgraph.layout() != ir::Layout::NCHW);
+
+ // TODO Different shape of deriv tensor
+ ir::OperandInfo backend_info{obj.shape(), obj.typeInfo(), obj.info().memAllocType(),
+ obj.isConstant()};
+ tensor_builder->registerBackwardTensorInfo(ind, backend_info, ir::Layout::NHWC);
+ });
+
+ // TODO Plan tensor builds to reduce peak memory usage
+ tgraph.operands().iterate([&](const ir::OperandIndex &ind, const ir::Operand &) {
+ if (tensor_builder->isRegisteredBackward(ind))
+ tensor_builder->notifyBackwardFirstUse(ind);
+ });
+
+ tensor_builder->allocateBackward();
+
+ return _tensor_registry.get();
+}
+
+FunctionMap BackendContext::genKernels()
+{
+ train::FunctionMap ret;
+
+ for (const auto &op_ind : _tdata->op_order)
+ {
+ auto fn_seq = kernel_gen->generate(op_ind);
+ ret.emplace_back(op_ind, std::move(fn_seq));
+ }
+
+ // Initialize TrainableTensors
+ trainable_graph()->operands().iterate(
+ [&](const ir::OperandIndex &ind, const ir::Operand &operand) {
+ if (external_operands().contains(ind) || !operand.isConstant())
+ return;
+
+ auto tensor = tensor_registry()->getNativeITensor(ind);
+ assert(tensor != nullptr);
+
+ VERBOSE(FillOperandData) << "Fill data for " << ind << std::endl;
+
+ auto data = operand.shareData();
+ assert(data && data->base());
+ auto trainable_tensor = dynamic_cast<TrainableTensor *>(tensor);
+
+ if (trainable_tensor == nullptr)
+ throw std::runtime_error{"This tensor is not trainable tensor"};
+
+ trainable_tensor->fillBuffer(data);
+ });
+
+ // NOTE For memory optimization, we want to free some operand data
+ const_cast<ir::train::TrainableGraph &>(*_tdata->tgraph)
+ .operands()
+ .iterate([&](const ir::OperandIndex &, ir::Operand &obj) { obj.releaseData(); });
+
+ // TODO Enable
+ // for (auto &&it : ret)
+ // {
+ // auto &fn_seq = it.second;
+ // fn_seq->iterate([&](exec::IFunction &ifunc) { ifunc.prepare(); });
+ // }
+
+ return ret;
+}
+
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/BackendContext.h b/runtime/onert/backend/train/BackendContext.h
new file mode 100644
index 000000000..b5b572b35
--- /dev/null
+++ b/runtime/onert/backend/train/BackendContext.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_TRAIN_BACKEND_CONTEXT_H__
+#define __ONERT_BACKEND_TRAIN_BACKEND_CONTEXT_H__
+
+#include <backend/train/TrainableBackendContext.h>
+
+#include "ExternalContext.h"
+#include "KernelGenerator.h"
+#include "TensorBuilder.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+// TODO Remove this class if ExecutorFactory creates trainable context only once instead of
+// replacing BackendContext
+class DummyBackendContext : public backend::BackendContext
+{
+public:
+ DummyBackendContext(const Backend *backend, ContextData &&data,
+ std::shared_ptr<backend::ITensorRegistry> tensor_registry = nullptr)
+ : backend::BackendContext(backend, std::move(data), tensor_registry)
+ {
+ }
+
+ backend::ITensorRegistry *genTensors() override { return nullptr; }
+
+ backend::FunctionMap genKernels() override { return backend::FunctionMap{}; }
+};
+
+// TODO Unify TensorBuilder
+// TODO Unify TensorRegistry
+class BackendContext : public onert::backend::train::TrainableBackendContext
+{
+public:
+ BackendContext(const ITrainableBackend *backend, std::unique_ptr<TrainableContextData> &&tdata,
+ std::shared_ptr<backend::train::ITensorRegistry> tensor_registry = nullptr,
+ std::shared_ptr<TensorBuilder> tensor_builder = nullptr,
+ std::shared_ptr<KernelGenerator> kernel_gen = nullptr)
+ : onert::backend::train::TrainableBackendContext(backend, std::move(tdata), tensor_registry),
+ kernel_gen{kernel_gen},
+ _external_context(new ExternalContext), _tensor_builder{tensor_builder}
+ {
+ }
+
+ backend::ITensorRegistry *genTensors() override;
+ backend::train::ITensorRegistry *genTrainingTensors() override;
+
+public:
+ FunctionMap genKernels() override;
+
+ std::shared_ptr<ExternalContext> external_context() { return _external_context; }
+
+public:
+ // TODO Make it private
+ std::shared_ptr<KernelGenerator> kernel_gen;
+
+private:
+ // NOTE ruy context has a thread pool, and when multiple ruy contexts are created,
+ // the thread pool is also created in duplicate
+ // TODO Create one ruy context for session
+ std::shared_ptr<ExternalContext> _external_context;
+
+private:
+ std::shared_ptr<TensorBuilder> _tensor_builder;
+};
+
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_BACKEND_CONTEXT_H__
diff --git a/runtime/onert/backend/train/CMakeLists.txt b/runtime/onert/backend/train/CMakeLists.txt
new file mode 100644
index 000000000..fd50685b4
--- /dev/null
+++ b/runtime/onert/backend/train/CMakeLists.txt
@@ -0,0 +1,20 @@
+set(LIB_ONERT_BACKEND_TRAIN onert_backend_train)
+
+file(GLOB_RECURSE SOURCES "*.cc")
+
+add_library(${LIB_ONERT_BACKEND_TRAIN} SHARED ${SOURCES})
+
+target_link_libraries(${LIB_ONERT_BACKEND_TRAIN} PRIVATE ${LIB_ONERT_BACKEND_CPU})
+target_link_libraries(${LIB_ONERT_BACKEND_TRAIN} PRIVATE onert_core)
+target_link_libraries(${LIB_ONERT_BACKEND_TRAIN} PRIVATE nnfw_lib_cker nnfw_lib_misc)
+target_link_libraries(${LIB_ONERT_BACKEND_TRAIN} PRIVATE nnfw_common)
+target_link_libraries(${LIB_ONERT_BACKEND_TRAIN} PRIVATE nnfw_coverage)
+
+set_target_properties(${LIB_ONERT_BACKEND_TRAIN} PROPERTIES OUTPUT_NAME backend_train)
+
+if(CMAKE_BUILD_TYPE_LC STREQUAL "release")
+ add_custom_command(TARGET ${LIB_ONERT_BACKEND_TRAIN} POST_BUILD
+ COMMAND ${CMAKE_STRIP} "--strip-unneeded" $<TARGET_FILE_NAME:${LIB_ONERT_BACKEND_TRAIN}>)
+endif()
+
+install(TARGETS ${LIB_ONERT_BACKEND_TRAIN} DESTINATION lib)
diff --git a/runtime/onert/backend/train/Config.cc b/runtime/onert/backend/train/Config.cc
new file mode 100644
index 000000000..57a68adc4
--- /dev/null
+++ b/runtime/onert/backend/train/Config.cc
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Config.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+bool Config::initialize() { return true; }
+
+ir::Layout Config::supportLayout(const ir::IOperation &, ir::Layout) { return ir::Layout::NHWC; }
+
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/Config.h b/runtime/onert/backend/train/Config.h
new file mode 100644
index 000000000..c8cf52b4d
--- /dev/null
+++ b/runtime/onert/backend/train/Config.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_TRAIN_CONFIG_H__
+#define __ONERT_BACKEND_TRAIN_CONFIG_H__
+
+#include <backend/IConfig.h>
+#include <util/ITimer.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+class Config : public IConfig
+{
+public:
+ std::string id() override { return "train"; }
+ bool initialize() override;
+ ir::Layout supportLayout(const ir::IOperation &node, ir::Layout frontend_layout) override;
+ bool supportPermutation() override { return true; }
+ bool supportDynamicTensor() override { return false; }
+ bool supportFP16() override { return false; }
+
+ std::unique_ptr<util::ITimer> timer() override { return std::make_unique<util::CPUTimer>(); }
+};
+
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_CONFIG_H__
diff --git a/runtime/onert/backend/train/ExternalContext.h b/runtime/onert/backend/train/ExternalContext.h
new file mode 100644
index 000000000..c24010ea2
--- /dev/null
+++ b/runtime/onert/backend/train/ExternalContext.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_TRAIN_EXTERNAL_CONTEXT_H__
+#define __ONERT_BACKEND_TRAIN_EXTERNAL_CONTEXT_H__
+
+#include <ExternalContext.h> // From cpu backend
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+using ExternalContext = cpu::ExternalContext;
+
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_EXTERNAL_CONTEXT_H__
diff --git a/runtime/onert/backend/train/KernelGenerator.cc b/runtime/onert/backend/train/KernelGenerator.cc
new file mode 100644
index 000000000..d3114e822
--- /dev/null
+++ b/runtime/onert/backend/train/KernelGenerator.cc
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "KernelGenerator.h"
+
+#include "ops/ConvolutionLayer.h"
+#include "ops/ElementwiseActivationLayer.h"
+#include "ops/FullyConnectedLayer.h"
+#include "ops/LossLayer.h"
+#include "ops/GradientApplier.h"
+#include "ops/PoolLayer.h"
+#include "ops/ReshapeLayer.h"
+
+#include <backend/Backend.h>
+#include <backend/IConfig.h>
+#include <memory>
+#include <util/Utils.h>
+#include <util/logging.h>
+#include <exec/DynamicShapeInferer.h>
+
+#include <stdexcept>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+namespace
+{
+ops::ElementwiseActivationType
+convertElementwiseActivationType(ir::operation::ElementwiseActivation::Type type_ir)
+{
+ switch (type_ir)
+ {
+ case ir::operation::ElementwiseActivation::Type::RELU:
+ return ops::ElementwiseActivationType::kReLU;
+ default:
+ throw std::runtime_error("train KernelGenerator : Not supported operation yet");
+ }
+}
+
+ops::LossType convertLossType(ir::operation::Loss::Type type_ir)
+{
+ switch (type_ir)
+ {
+ case ir::operation::Loss::Type::MEAN_SQUARED_ERROR:
+ return ops::LossType::kMSE;
+ default:
+ throw std::runtime_error("train KernelGenerator : Not supported operation yet");
+ }
+}
+
+ops::PoolType convertPoolType(ir::operation::Pool2D::PoolType type_ir)
+{
+ switch (type_ir)
+ {
+ // TODO Implement AVG PoolType
+ case ir::operation::Pool2D::PoolType::MAX:
+ return ops::PoolType::kMax;
+ default:
+ throw std::runtime_error("train KernelGenerator : Not supported operation yet");
+ }
+}
+
+std::unique_ptr<ops::GradientApplier>
+generateGradientApplier(const std::shared_ptr<exec::train::optimizer::Optimizer> optimizer,
+ const IPortableTensor *gradient, ITrainableTensor *trainable)
+{
+ auto update_fn = std::make_unique<ops::GradientApplier>();
+ update_fn->configure(optimizer, gradient, trainable);
+ return update_fn;
+}
+} // namespace
+
+std::unique_ptr<exec::train::TrainableFnSequence> KernelGenerator::generate(ir::OperationIndex idx)
+{
+ auto ret = std::make_unique<exec::train::TrainableFnSequence>();
+
+ const auto &op = _tgraph.operation(idx);
+ op.accept(*this);
+ assert(_return_fn);
+ ret->append(std::move(_return_fn));
+
+ for (auto &&update_fn : _update_funcs)
+ ret->append(std::move(update_fn));
+ _update_funcs.clear();
+
+ for (auto &&ind : (op.getInputs() | ir::Remove::UNDEFINED) + op.getOutputs())
+ {
+ auto portable_tensor = _tensor_reg->getPortableTensor(ind);
+ if (portable_tensor)
+ {
+ assert(portable_tensor->layout() == ir::Layout::NHWC);
+ }
+ auto tensor = _tensor_reg->getNonConstTensor(ind);
+ if (tensor)
+ {
+ tensor->increase_ref();
+ }
+ }
+ return ret;
+}
+
+KernelGenerator::KernelGenerator(const ir::train::TrainableGraph &tgraph,
+ const std::shared_ptr<TensorRegistry> &tensor_reg,
+ const std::shared_ptr<ExternalContext> &external_context,
+ std::shared_ptr<exec::train::optimizer::Optimizer> optimizer)
+ : backend::train::KernelGeneratorBase{tgraph}, _current_layout{tgraph.layout()},
+ _tensor_reg{tensor_reg},
+ _external_context(external_context), _optimizer{optimizer}, _update_funcs{}
+{
+ // DO NOTHING
+}
+
+void KernelGenerator::visit(const ir::train::operation::Conv2D &node)
+{
+ // TODO Generate kernel
+
+ // Generate GradientApplier
+ const auto ker_index{node.getInputs().at(ir::train::operation::Conv2D::Input::KERNEL)};
+
+ auto grad_tensor = _tensor_reg->getGradientTensor(ker_index);
+ auto ker_tensor = _tensor_reg->getTrainableTensor(ker_index);
+
+ auto update_fn = std::make_unique<ops::GradientApplier>();
+
+ update_fn->configure(_optimizer, grad_tensor, ker_tensor);
+
+ _update_funcs.emplace_back(generateGradientApplier(_optimizer, grad_tensor, ker_tensor));
+}
+
+void KernelGenerator::visit(const ir::train::operation::ElementwiseActivation &node)
+{
+ using ir::train::operation::ElementwiseActivation;
+
+ const auto output_index{node.getOutputs().at(0)};
+ const auto input_index{node.getInputs().at(ElementwiseActivation::Input::INPUT)};
+
+ auto output_tensor = _tensor_reg->getPortableTensor(output_index);
+ auto input_tensor = _tensor_reg->getPortableTensor(input_index);
+
+ auto deriv_input_tensor = _tensor_reg->getDerivativeTensor(input_index);
+ auto deriv_output_tensor = _tensor_reg->getDerivativeTensor(output_index);
+
+ auto fn = std::make_unique<ops::ElementwiseActivationLayer>();
+
+ fn->configure(input_tensor, output_tensor, deriv_input_tensor, deriv_output_tensor,
+ node.param().alpha, node.param().beta,
+ convertElementwiseActivationType(node.param().op_type));
+
+ _return_fn = std::move(fn);
+}
+
+void KernelGenerator::visit(const ir::train::operation::FullyConnected &node)
+{
+ using ir::train::operation::FullyConnected;
+
+ const auto out_index{node.getOutputs().at(0)};
+ const auto in_index{node.getInputs().at(FullyConnected::Input::INPUT)};
+ const auto weights_index{node.getInputs().at(FullyConnected::Input::WEIGHT)};
+ const auto bias_index{node.getInputs().at(FullyConnected::Input::BIAS)};
+
+ auto out_tensor = _tensor_reg->getPortableTensor(out_index);
+ auto in_tensor = _tensor_reg->getPortableTensor(in_index);
+ auto weights_tensor = _tensor_reg->getTrainableTensor(weights_index);
+ auto bias_tensor = _tensor_reg->getTrainableTensor(bias_index);
+
+ auto out_deriv_tensor = _tensor_reg->getDerivativeTensor(out_index);
+ auto in_deriv_tensor = _tensor_reg->getDerivativeTensor(in_index);
+ auto weights_grad_tensor = _tensor_reg->getGradientTensor(weights_index);
+ auto bias_grad_tensor = _tensor_reg->getGradientTensor(bias_index);
+
+ // Generate kernel
+ const auto activation = node.param().activation;
+ const auto weights_format = node.param().weights_format;
+
+ auto fn = std::make_unique<ops::FullyConnectedLayer>();
+
+ fn->configure(in_tensor, weights_tensor, bias_tensor, out_tensor, in_deriv_tensor,
+ weights_grad_tensor, bias_grad_tensor, out_deriv_tensor, activation, weights_format,
+ _external_context);
+
+ _return_fn = std::move(fn);
+
+ // Generate GradientAppliers
+ if (bias_tensor)
+ _update_funcs.emplace_back(generateGradientApplier(_optimizer, bias_grad_tensor, bias_tensor));
+ _update_funcs.emplace_back(
+ generateGradientApplier(_optimizer, weights_grad_tensor, weights_tensor));
+}
+
+void KernelGenerator::visit(const ir::train::operation::Loss &node)
+{
+ using ir::train::operation::Loss;
+
+ const auto output_index{node.getOutputs().at(0)};
+ const auto y_pred_index{node.getInputs().at(Loss::Y_PRED)};
+ const auto y_true_index{node.getInputs().at(Loss::Y_TRUE)};
+
+ auto output_tensor = _tensor_reg->getPortableTensor(output_index);
+ auto y_pred_tensor = _tensor_reg->getPortableTensor(y_pred_index);
+ auto y_true_tensor = _tensor_reg->getPortableTensor(y_true_index);
+
+ auto deriv_y_pred_tensor = _tensor_reg->getDerivativeTensor(y_pred_index);
+ auto fn = std::make_unique<ops::LossLayer>();
+
+ fn->configure(y_pred_tensor, y_true_tensor, output_tensor, deriv_y_pred_tensor,
+ convertLossType(node.param().op_type));
+
+ _return_fn = std::move(fn);
+
+ UNUSED_RELEASE(convertPoolType);
+}
+
+void KernelGenerator::visit(const ir::train::operation::Reshape &node)
+{
+ using ir::train::operation::Reshape;
+
+ const auto output_index{node.getOutputs().at(0)};
+ const auto input_index{node.getInputs().at(ir::operation::Reshape::Input::INPUT)};
+
+ auto output_tensor = _tensor_reg->getPortableTensor(output_index);
+ auto input_tensor = _tensor_reg->getPortableTensor(input_index);
+
+ auto output_deriv_tensor = _tensor_reg->getDerivativeTensor(output_index);
+ auto input_deriv_tensor = _tensor_reg->getDerivativeTensor(input_index);
+
+ // optional 2nd input
+ IPortableTensor *shape_tensor = nullptr;
+
+ if (node.getInputs().size() == 2)
+ {
+ const auto shape_index{node.getInputs().at(ir::operation::Reshape::Input::SHAPE)};
+ shape_tensor = _tensor_reg->getPortableTensor(shape_index);
+ }
+
+ auto fn = std::make_unique<ops::ReshapeLayer>();
+
+ fn->configure(input_tensor, shape_tensor, output_tensor, input_deriv_tensor, output_deriv_tensor);
+ _return_fn = std::move(fn);
+}
+
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/KernelGenerator.h b/runtime/onert/backend/train/KernelGenerator.h
new file mode 100644
index 000000000..660dc5d70
--- /dev/null
+++ b/runtime/onert/backend/train/KernelGenerator.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_TRAIN_KERNEL_GENERATOR_H__
+#define __ONERT_BACKEND_TRAIN_KERNEL_GENERATOR_H__
+
+#include "ExternalContext.h"
+#include "backend/basic/TensorRegistry.h"
+#include "TensorBuilder.h"
+#include "Tensor.h"
+
+#include <backend/train/KernelGeneratorBase.h>
+#include <exec/train/IGradientApplier.h>
+#include <exec/train/optimizer/Optimizer.h>
+#include <ir/Operands.h>
+#include <ir/Operations.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+// TODO Unify TensorRegistry
+class KernelGenerator : public backend::train::KernelGeneratorBase
+{
+public:
+ KernelGenerator(const ir::train::TrainableGraph &tgraph,
+ const std::shared_ptr<TensorRegistry> &tensor_reg,
+ const std::shared_ptr<ExternalContext> &external_context,
+ std::shared_ptr<exec::train::optimizer::Optimizer> optimizer);
+
+ std::unique_ptr<exec::train::TrainableFnSequence> generate(ir::OperationIndex op_ind) override;
+
+ void visit(const ir::train::operation::Conv2D &) override;
+ void visit(const ir::train::operation::ElementwiseActivation &) override;
+ void visit(const ir::train::operation::FullyConnected &) override;
+ void visit(const ir::train::operation::Loss &) override;
+ void visit(const ir::train::operation::Reshape &node) override;
+
+private:
+ ir::Layout _current_layout;
+ std::shared_ptr<TensorRegistry> _tensor_reg;
+ const std::shared_ptr<ExternalContext> _external_context;
+ std::shared_ptr<exec::train::optimizer::Optimizer> _optimizer;
+ std::vector<std::unique_ptr<exec::train::IGradientApplier>> _update_funcs;
+};
+
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_KERNEL_GENERATOR_H__
diff --git a/runtime/onert/backend/train/MemoryManager.h b/runtime/onert/backend/train/MemoryManager.h
new file mode 100644
index 000000000..6ac57996f
--- /dev/null
+++ b/runtime/onert/backend/train/MemoryManager.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_TRAIN_MEMORY_MANAGER_H__
+#define __ONERT_BACKEND_TRAIN_MEMORY_MANAGER_H__
+
+#include <backend/basic/MemoryManager.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+using MemoryManager = backend::basic::MemoryManager;
+
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_MEMORY_MANAGER_H__
diff --git a/runtime/onert/backend/train/Tensor.h b/runtime/onert/backend/train/Tensor.h
new file mode 100644
index 000000000..34a3cc191
--- /dev/null
+++ b/runtime/onert/backend/train/Tensor.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_TRAIN_TENSOR_H__
+#define __ONERT_BACKEND_TRAIN_TENSOR_H__
+
+#include <backend/basic/Tensor.h>
+#include <backend/basic/train/TrainableTensor.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+// NOTE This class can be replaced with basic::Tensor if this backend supports dynamic tensors.
+class Tensor : public basic::Tensor
+{
+public:
+ Tensor() = delete;
+
+public:
+ Tensor(const ir::OperandInfo &info, const ir::Layout layout)
+ : basic::Tensor{info, layout, nullptr}
+ {
+ // DO NOTHING
+ }
+
+public:
+ bool applyShape(const ir::Shape &) override { return false; }
+};
+
+using TrainableTensor = basic::train::TrainableTensor;
+using DerivativeTensor = Tensor;
+using GradientTensor = Tensor;
+
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_TENSOR_H__
diff --git a/runtime/onert/backend/train/TensorBuilder.cc b/runtime/onert/backend/train/TensorBuilder.cc
new file mode 100644
index 000000000..99e06d3a4
--- /dev/null
+++ b/runtime/onert/backend/train/TensorBuilder.cc
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TensorBuilder.h"
+
+#include "Tensor.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+TensorBuilder::TensorBuilder(const std::shared_ptr<TensorRegistry> &tensor_reg,
+ const std::string planner_id)
+ : _tensor_reg{tensor_reg}, _tensor_mgr{new TensorManager(tensor_reg, planner_id)}
+{
+ /* empty */
+}
+
+void TensorBuilder::registerTensorInfo(const ir::OperandIndex &index, const ir::OperandInfo &info,
+ ir::Layout layout)
+{
+ _tensor_info_map.emplace(index, info);
+ _as_constants[index] = info.isConstant();
+
+ // Train backend supports only one layout as NHWC
+ assert(layout == ir::Layout::NHWC);
+ assert(!info.isDynamic());
+
+ // NOTE For now, whether or not to build operands to trainable tensor depends on whether
+ // the corresponding operand is constant.
+ if (_as_constants[index])
+ {
+ auto tensor = std::make_unique<TrainableTensor>(info, layout);
+ _tensor_reg->setTrainableTensor(index, std::move(tensor));
+ }
+ else
+ {
+ auto tensor = std::make_unique<Tensor>(info, layout);
+ _tensor_reg->setNonConstTensor(index, std::move(tensor));
+ }
+}
+
+void TensorBuilder::registerBackwardTensorInfo(const ir::OperandIndex &index,
+ const ir::OperandInfo &info, ir::Layout layout)
+{
+ _backward_tensor_info_map.emplace(index, info);
+
+ // Train backend supports only one layout as NHWC
+ assert(layout == ir::Layout::NHWC);
+ assert(!info.isDynamic());
+
+ // NOTE For now, whether or not to build operands to trainable tensor depends on whether
+ // the corresponding operand is constant.
+ assert(_as_constants[index] == info.isConstant());
+ if (_as_constants[index])
+ {
+ auto tensor = std::make_unique<GradientTensor>(info, layout);
+ _tensor_reg->setGradientTensor(index, std::move(tensor));
+ }
+ else
+ {
+ auto tensor = std::make_unique<DerivativeTensor>(info, layout);
+ _tensor_reg->setDerivativeTensor(index, std::move(tensor));
+ }
+}
+
+void TensorBuilder::notifyFirstUse(const ir::OperandIndex &index)
+{
+ // TODO Support momory plan
+ if (_as_constants[index])
+ {
+ _tensor_mgr->claimTrainablePlan(index);
+ }
+ else
+ {
+ _tensor_mgr->claimNonConstPlan(index);
+ }
+}
+
+void TensorBuilder::notifyLastUse(const ir::OperandIndex &)
+{
+ // TODO Support momory plan
+}
+
+void TensorBuilder::notifyBackwardFirstUse(const ir::OperandIndex &index)
+{
+ // TODO Support momory plan
+ if (_as_constants[index])
+ {
+ _tensor_mgr->claimGradientPlan(index);
+ }
+ else
+ {
+ _tensor_mgr->claimDerivativePlan(index);
+ }
+}
+
+bool TensorBuilder::isRegistered(const ir::OperandIndex &index) const
+{
+ return _tensor_info_map.find(index) != _tensor_info_map.end();
+}
+
+bool TensorBuilder::isRegisteredBackward(const ir::OperandIndex &index) const
+{
+ return _backward_tensor_info_map.find(index) != _backward_tensor_info_map.end();
+}
+
+void TensorBuilder::allocate(void)
+{
+ _tensor_mgr->allocateNonConstTensors();
+ _tensor_mgr->allocateTrainableTensors();
+}
+
+void TensorBuilder::allocateBackward(void)
+{
+ _tensor_mgr->allocateDerivativeTensors();
+ _tensor_mgr->allocateGradientTensors();
+}
+
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/TensorBuilder.h b/runtime/onert/backend/train/TensorBuilder.h
new file mode 100644
index 000000000..d0738fe68
--- /dev/null
+++ b/runtime/onert/backend/train/TensorBuilder.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_TRAIN_TENSOR_BUILDER_H__
+#define __ONERT_BACKEND_TRAIN_TENSOR_BUILDER_H__
+
+#include "TensorManager.h"
+#include "TensorRegistry.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+// TODO Support dynamic tensors
+class TensorBuilder
+{
+public:
+ TensorBuilder(const std::shared_ptr<TensorRegistry> &tensor_reg, const std::string planner_id);
+
+ /**
+ * @brief Register tensor information to allocate on train backend
+ * @param[in] ind Operand index
+ * @param[in] info Operand information
+ * @param[in] layout Operand data layout
+ */
+ void registerTensorInfo(const ir::OperandIndex &ind, const ir::OperandInfo &info,
+ ir::Layout backend_layout);
+
+ /**
+ * @brief Register informations of tensor used only in backward to allocate on train backend
+ * @param[in] ind Operand index
+ * @param[in] info Operand information
+ * @param[in] layout Operand data layout
+ */
+ void registerBackwardTensorInfo(const ir::OperandIndex &ind, const ir::OperandInfo &info,
+ ir::Layout backend_layout);
+
+ // TODO Support memory plan of all tensors
+ void notifyFirstUse(const ir::OperandIndex &);
+ void notifyLastUse(const ir::OperandIndex &);
+ void notifyBackwardFirstUse(const ir::OperandIndex &);
+
+ bool isRegistered(const ir::OperandIndex &) const;
+ bool isRegisteredBackward(const ir::OperandIndex &) const;
+
+ void allocate(void);
+ void allocateBackward(void);
+
+private:
+ const std::shared_ptr<TensorRegistry> _tensor_reg;
+ std::unique_ptr<TensorManager> _tensor_mgr;
+ ir::OperandIndexMap<ir::OperandInfo> _tensor_info_map;
+ ir::OperandIndexMap<ir::OperandInfo> _backward_tensor_info_map;
+ ir::OperandIndexMap<bool> _as_constants;
+};
+
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_TENSOR_BUILDER_H__
diff --git a/runtime/onert/backend/train/TensorManager.cc b/runtime/onert/backend/train/TensorManager.cc
new file mode 100644
index 000000000..50144a78f
--- /dev/null
+++ b/runtime/onert/backend/train/TensorManager.cc
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TensorManager.h"
+
+#include <util/logging.h>
+
+namespace
+{
+
+using namespace onert;
+
+template <typename Tensor>
+void allocateMemory(backend::train::MemoryManager *mgr,
+ const ir::OperandIndexMap<std::unique_ptr<Tensor>> &tensors,
+ const std::string tensor_type)
+{
+ mgr->allocate();
+
+ for (auto &&pair : tensors)
+ {
+ const auto &index = pair.first;
+ auto tensor = pair.second.get();
+ assert(!tensor->is_dynamic());
+
+ auto *buffer = mgr->getBuffer(index);
+ tensor->setBuffer(buffer);
+ VERBOSE(TensorManager) << tensor_type << index << " : " << static_cast<void *>(buffer)
+ << std::endl;
+ }
+}
+
+} // namespace
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+TensorManager::TensorManager(const std::shared_ptr<TensorRegistry> &reg,
+ const std::string planner_id)
+ : _nonconst_mgr{new MemoryManager(planner_id)}, _trainable_mgr{new MemoryManager(planner_id)},
+ _derivative_mgr{new MemoryManager(planner_id)},
+ _gradient_mgr{new MemoryManager(planner_id)}, _tensors{reg}
+{
+ // DO NOTHING
+}
+
+void TensorManager::allocateNonConstTensors()
+{
+ allocateMemory(_nonconst_mgr.get(), _tensors->nonconst_tensors(),
+ std::string{" TENSOR "});
+}
+
+void TensorManager::allocateTrainableTensors()
+{
+ allocateMemory(_trainable_mgr.get(), _tensors->trainable_tensors(),
+ std::string{"TRAINABLE TENSOR "});
+}
+
+void TensorManager::allocateDerivativeTensors()
+{
+ allocateMemory(_derivative_mgr.get(), _tensors->derivative_tensors(),
+ std::string{"DERIVATIVE TENSOR "});
+}
+
+void TensorManager::allocateGradientTensors()
+{
+ allocateMemory(_gradient_mgr.get(), _tensors->gradient_tensors(),
+ std::string{"GRADIENT TENSOR "});
+}
+
+void TensorManager::claimNonConstPlan(const ir::OperandIndex &index)
+{
+ auto tensor = _tensors->getNonConstTensor(index);
+ assert(tensor && !tensor->is_dynamic());
+
+ auto size = tensor->total_size();
+ _nonconst_mgr->claimPlan(index, size);
+}
+
+void TensorManager::releaseNonConstPlan(const ir::OperandIndex &index)
+{
+ assert(_tensors->getNonConstTensor(index) && !_tensors->getNonConstTensor(index)->is_dynamic());
+
+ _nonconst_mgr->releasePlan(index);
+}
+
+void TensorManager::claimTrainablePlan(const ir::OperandIndex &index)
+{
+ auto tensor = _tensors->getTrainableTensor(index);
+ assert(tensor && !tensor->is_dynamic());
+
+ auto size = tensor->total_size();
+ _trainable_mgr->claimPlan(index, size);
+}
+
+void TensorManager::releaseTrainablePlan(const ir::OperandIndex &index)
+{
+ assert(_tensors->getTrainableTensor(index) && !_tensors->getTrainableTensor(index)->is_dynamic());
+
+ _trainable_mgr->releasePlan(index);
+}
+
+void TensorManager::claimDerivativePlan(const ir::OperandIndex &index)
+{
+ auto tensor = _tensors->getDerivativeTensor(index);
+ assert(tensor && !tensor->is_dynamic());
+
+ auto size = tensor->total_size();
+ _derivative_mgr->claimPlan(index, size);
+}
+
+void TensorManager::releaseDerivativePlan(const ir::OperandIndex &index)
+{
+ assert(_tensors->getDerivativeTensor(index) &&
+ !_tensors->getDerivativeTensor(index)->is_dynamic());
+
+ _derivative_mgr->releasePlan(index);
+}
+
+void TensorManager::claimGradientPlan(const ir::OperandIndex &index)
+{
+ auto tensor = _tensors->getGradientTensor(index);
+ assert(tensor && !tensor->is_dynamic());
+
+ auto size = tensor->total_size();
+ _gradient_mgr->claimPlan(index, size);
+}
+
+void TensorManager::releaseGradientPlan(const ir::OperandIndex &index)
+{
+ assert(_tensors->getGradientTensor(index) && !_tensors->getGradientTensor(index)->is_dynamic());
+
+ _gradient_mgr->releasePlan(index);
+}
+
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/TensorManager.h b/runtime/onert/backend/train/TensorManager.h
new file mode 100644
index 000000000..06da3edd7
--- /dev/null
+++ b/runtime/onert/backend/train/TensorManager.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_TRAIN_TENSOR_MANAGER_H__
+#define __ONERT_BACKEND_TRAIN_TENSOR_MANAGER_H__
+
+#include "MemoryManager.h"
+#include "TensorRegistry.h"
+
+#include <ir/OperandIndexMap.h>
+#include <ir/OperandInfo.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+class TensorManager
+{
+public:
+ TensorManager(const std::shared_ptr<TensorRegistry> &reg, const std::string planner_id);
+ virtual ~TensorManager() = default;
+
+ void allocateNonConstTensors();
+ void allocateTrainableTensors();
+ void allocateDerivativeTensors();
+ void allocateGradientTensors();
+ // TODO Add member functions to deallocate tensors
+
+ void claimNonConstPlan(const ir::OperandIndex &ind);
+ void releaseNonConstPlan(const ir::OperandIndex &ind);
+ void claimTrainablePlan(const ir::OperandIndex &ind);
+ void releaseTrainablePlan(const ir::OperandIndex &ind);
+ void claimDerivativePlan(const ir::OperandIndex &ind);
+ void releaseDerivativePlan(const ir::OperandIndex &ind);
+ void claimGradientPlan(const ir::OperandIndex &ind);
+ void releaseGradientPlan(const ir::OperandIndex &ind);
+
+private:
+ std::unique_ptr<MemoryManager> _nonconst_mgr;
+ std::unique_ptr<MemoryManager> _trainable_mgr;
+ std::unique_ptr<MemoryManager> _derivative_mgr;
+ std::unique_ptr<MemoryManager> _gradient_mgr;
+ const std::shared_ptr<TensorRegistry> _tensors;
+};
+
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_TENSOR_MANAGER_H__
diff --git a/runtime/onert/backend/train/TensorRegistry.h b/runtime/onert/backend/train/TensorRegistry.h
new file mode 100644
index 000000000..34aeb0fcd
--- /dev/null
+++ b/runtime/onert/backend/train/TensorRegistry.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_TRAIN_TENSOR_REGISTRY__
+#define __ONERT_BACKEND_TRAIN_TENSOR_REGISTRY__
+
+#include <backend/train/ITensorRegistry.h>
+
+#include "Tensor.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+using TensorRegistry =
+ PortableTensorRegistryTemplate<Tensor, TrainableTensor, DerivativeTensor, GradientTensor>;
+
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_TENSOR_REGISTRY__
diff --git a/runtime/onert/backend/train/ops/ConvolutionLayer.cc b/runtime/onert/backend/train/ops/ConvolutionLayer.cc
new file mode 100644
index 000000000..ac736c34d
--- /dev/null
+++ b/runtime/onert/backend/train/ops/ConvolutionLayer.cc
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ConvolutionLayer.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+ConvolutionLayer::ConvolutionLayer() : cpu::ops::ConvolutionLayer()
+{
+ // DO NOTHING
+}
+
+ConvolutionLayer::~ConvolutionLayer() = default;
+
+void ConvolutionLayer::configure(const IPortableTensor *input, const IPortableTensor *kernel,
+ const IPortableTensor *bias, const ir::PaddingType paddingType,
+ const uint32_t paddingLeft, const uint32_t paddingRight,
+ const uint32_t paddingTop, const uint32_t paddingBottom,
+ const uint32_t strideWidth, const uint32_t strideHeight,
+ const uint32_t dilationWidthFactor,
+ const uint32_t dilationHeightFactor,
+ const ir::Activation activation, IPortableTensor *output)
+{
+ cpu::ops::ConvolutionLayer::configure(
+ input, kernel, bias, paddingType, paddingLeft, paddingRight, paddingTop, paddingBottom,
+ strideWidth, strideHeight, dilationWidthFactor, dilationHeightFactor, activation, output);
+}
+
+void ConvolutionLayer::forward(bool) { cpu::ops::ConvolutionLayer::run(); }
+void ConvolutionLayer::backward()
+{
+ // TODO Implement detail
+}
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/ops/ConvolutionLayer.h b/runtime/onert/backend/train/ops/ConvolutionLayer.h
new file mode 100644
index 000000000..ed42a2099
--- /dev/null
+++ b/runtime/onert/backend/train/ops/ConvolutionLayer.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_TRAIN_OPS_CONVOLUTIONLAYER_H__
+#define __ONERT_BACKEND_TRAIN_OPS_CONVOLUTIONLAYER_H__
+
+#include <ops/ConvolutionLayer.h>
+
+#include <exec/train/ITrainableFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+class ConvolutionLayer : public ::onert::exec::train::ITrainableFunction,
+ public cpu::ops::ConvolutionLayer
+{
+public:
+ ConvolutionLayer();
+ ~ConvolutionLayer();
+
+ void configure(const IPortableTensor *input, const IPortableTensor *kernel,
+ const IPortableTensor *bias, ir::PaddingType _paddingType,
+ const uint32_t paddingLeft, const uint32_t paddingRight, const uint32_t paddingTop,
+ const uint32_t paddingBottom, const uint32_t strideWidth,
+ const uint32_t strideHeight, const uint32_t dilationWidthFactor,
+ const uint32_t dilationHeightFactor, const ir::Activation activation,
+ IPortableTensor *output);
+ void forward(bool training) override;
+ void backward() override;
+};
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_OPS_CONVOLUTIONLAYER_H__
diff --git a/runtime/onert/backend/train/ops/ElementwiseActivationLayer.cc b/runtime/onert/backend/train/ops/ElementwiseActivationLayer.cc
new file mode 100644
index 000000000..860eca43c
--- /dev/null
+++ b/runtime/onert/backend/train/ops/ElementwiseActivationLayer.cc
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ElementwiseActivationLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/train/operation/ReLU.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+ElementwiseActivationLayer::ElementwiseActivationLayer() : cpu::ops::ElementwiseActivationLayer()
+{
+ // DO NOTHING
+}
+
+void ElementwiseActivationLayer::configure(const IPortableTensor *input, IPortableTensor *output,
+ IPortableTensor *deriv_input,
+ const IPortableTensor *deriv_output, float alpha,
+ float beta, ElementwiseActivationType op_type)
+{
+ assert(input != nullptr);
+ assert(output != nullptr);
+ assert(deriv_input != nullptr);
+ assert(deriv_output != nullptr);
+
+ _deriv_input = deriv_input;
+ _deriv_output = deriv_output;
+
+ _op_type = op_type;
+
+ switch (op_type)
+ {
+ case ElementwiseActivationType::kReLU:
+ if (input->data_type() == OperandType::FLOAT32)
+ {
+ if (alpha == std::numeric_limits<float>::infinity() && beta == 0.f)
+ {
+ cpu::ops::ElementwiseActivationLayer::configure(
+ input, output, alpha, beta, cpu::ops::ElementwiseActivationType::kReLU);
+
+ _backward_kernel = [](const IPortableTensor *output, const IPortableTensor *incoming,
+ IPortableTensor *outgoing) {
+ nnfw::cker::train::ReLUGrad(getShape(output), getBuffer<float>(output),
+ getShape(incoming), getBuffer<float>(incoming),
+ getShape(outgoing), getBuffer<float>(outgoing));
+ };
+ }
+ else
+ {
+ throw std::runtime_error("train ElementwiseActivationLayer : This layer does not "
+ "suppport other ReLU except for ReLU(0-inf)");
+ }
+ }
+ else
+ {
+ throw std::runtime_error("train ElementwiseActivationLayer: Unsupported datatype");
+ }
+ break;
+ default:
+ throw std::runtime_error("train ElementwiseActivationLayer: Unsupported activation type yet");
+ }
+}
+
+void ElementwiseActivationLayer::forward(bool) { cpu::ops::ElementwiseActivationLayer::run(); }
+
+void ElementwiseActivationLayer::backward()
+{
+ _backward_kernel(_output, _deriv_output, _deriv_input);
+}
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/ops/ElementwiseActivationLayer.h b/runtime/onert/backend/train/ops/ElementwiseActivationLayer.h
new file mode 100644
index 000000000..dac1efe92
--- /dev/null
+++ b/runtime/onert/backend/train/ops/ElementwiseActivationLayer.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_TRAIN_OPS_ELEMENTWISEACTIVATIONLAYER_H__
+#define __ONERT_BACKEND_TRAIN_OPS_ELEMENTWISEACTIVATIONLAYER_H__
+
+#include <backend/IPortableTensor.h>
+#include <ops/ElementwiseActivationLayer.h>
+
+#include <exec/train/ITrainableFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+enum class ElementwiseActivationType
+{
+ kReLU,
+};
+
+class ElementwiseActivationLayer : public ::onert::exec::train::ITrainableFunction,
+ public cpu::ops::ElementwiseActivationLayer
+{
+public:
+ ElementwiseActivationLayer();
+
+ void configure(const IPortableTensor *input, IPortableTensor *output,
+ IPortableTensor *deriv_input, const IPortableTensor *deriv_output, float alpha,
+ float beta, ElementwiseActivationType op_type);
+ void forward(bool training) override;
+ void backward() override;
+
+private:
+ IPortableTensor *_deriv_input;
+ const IPortableTensor *_deriv_output;
+
+ ElementwiseActivationType _op_type;
+ std::function<void(const IPortableTensor *output, const IPortableTensor *incoming,
+ IPortableTensor *outgoing)>
+ _backward_kernel;
+};
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_OPS_ELEMENTWISEACTIVATIONLAYER_H__
diff --git a/runtime/onert/backend/train/ops/FullyConnectedLayer.cc b/runtime/onert/backend/train/ops/FullyConnectedLayer.cc
new file mode 100644
index 000000000..8fdc822d2
--- /dev/null
+++ b/runtime/onert/backend/train/ops/FullyConnectedLayer.cc
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FullyConnectedLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/operation/FullyConnected.h>
+#include <cker/operation/Transpose.h>
+#include <cker/train/operation/FullyConnected.h>
+#include <cker/train/operation/ReLU.h>
+
+namespace
+{
+
+using namespace onert;
+
+std::unique_ptr<backend::train::Tensor>
+createTransposedTensor(const backend::IPortableTensor *origin_tensor)
+{
+ const auto &origin_shape = origin_tensor->getShape();
+ assert(origin_shape.rank() == 2);
+
+ auto transposed_info = origin_tensor->get_info();
+ auto transposed_shape = ir::Shape{origin_shape.dim(1), origin_shape.dim(0)};
+ transposed_info.shape(transposed_shape);
+
+ return std::make_unique<backend::train::Tensor>(transposed_info, origin_tensor->layout());
+}
+
+} // namespace
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+FullyConnectedLayer::FullyConnectedLayer()
+ : cpu::ops::FullyConnectedLayer{}, _grad_weights{nullptr}, _grad_bias{nullptr},
+ _deriv_input{nullptr}, _deriv_output{nullptr}, _transposed_weights{nullptr},
+ _transposed_input{nullptr}, _transposed_deriv_output{nullptr}, _act_deriv_output{nullptr}
+{
+ // DO NOTHING
+}
+
+FullyConnectedLayer::~FullyConnectedLayer() = default;
+
+void FullyConnectedLayer::configure(const IPortableTensor *input, const IPortableTensor *weights,
+ const IPortableTensor *bias, IPortableTensor *output,
+ IPortableTensor *deriv_input, IPortableTensor *grad_weights,
+ IPortableTensor *grad_bias, const IPortableTensor *deriv_output,
+ ir::Activation activation,
+ ir::FullyConnectedWeightsFormat weights_format,
+ const std::shared_ptr<train::ExternalContext> &external_context)
+{
+ cpu::ops::FullyConnectedLayer::configure(input, weights, bias, activation, weights_format, output,
+ external_context);
+
+ _deriv_input = deriv_input;
+ _grad_weights = grad_weights;
+ _grad_bias = grad_bias;
+ _deriv_output = deriv_output;
+
+ if (weights_format != ir::FullyConnectedWeightsFormat::Default)
+ throw std::runtime_error{
+ "train FullyConnectedLayer: Weight formats other than default are not supported."};
+
+ if (input->get_info().shape().rank() != 2 || weights->get_info().shape().rank() != 2 ||
+ output->get_info().shape().rank() != 2 || deriv_input->get_info().shape().rank() != 2 ||
+ grad_weights->get_info().shape().rank() != 2 || deriv_output->get_info().shape().rank() != 2)
+ throw std::runtime_error{
+ "train FullyConnectedLayer: Input other ranks than 2 are not supported."};
+
+ _transposed_weights = createTransposedTensor(weights);
+ _transposed_weights->setBuffer(std::make_shared<basic::Allocator>(weights->total_size()));
+
+ _transposed_input = createTransposedTensor(input);
+ _transposed_input->setBuffer(std::make_shared<basic::Allocator>(input->total_size()));
+
+ _transposed_deriv_output = createTransposedTensor(deriv_output);
+ _transposed_deriv_output->setBuffer(
+ std::make_shared<basic::Allocator>(deriv_output->total_size()));
+
+ if (activation != ir::Activation::NONE)
+ {
+ _act_deriv_output =
+ std::make_unique<Tensor>(_deriv_output->get_info(), _deriv_output->layout());
+ _act_deriv_output->setBuffer(std::make_shared<basic::Allocator>(_deriv_output->total_size()));
+ }
+}
+
+void FullyConnectedLayer::forward(bool) { cpu::ops::FullyConnectedLayer::run(); }
+
+void FullyConnectedLayer::backward()
+{
+ const auto data_type = _deriv_output->data_type();
+ assert(data_type == _input->data_type());
+ switch (data_type)
+ {
+ case OperandType::FLOAT32:
+ {
+ assert(data_type == _grad_weights->data_type());
+ assert(data_type == _grad_bias->data_type());
+ backwardFloat32();
+ break;
+ }
+ default:
+ throw std::runtime_error{"train FullyConnectedLayer: unsupported data type"};
+ }
+}
+
+void FullyConnectedLayer::backwardFloat32()
+{
+ // Calculate gradient for activation
+ const IPortableTensor *backprop_act;
+ switch (_activation)
+ {
+ case ir::Activation::NONE:
+ backprop_act = _deriv_output;
+ break;
+ case ir::Activation::RELU:
+ nnfw::cker::train::ReLUGrad(getShape(_output), getBuffer<float>(_output),
+ getShape(_deriv_output), getBuffer<float>(_deriv_output),
+ getShape(_act_deriv_output.get()),
+ getBuffer<float>(_act_deriv_output.get()));
+ backprop_act = _act_deriv_output.get();
+ break;
+ default:
+ throw std::runtime_error("train FullyConnectedLayer: Unsupported activation type yet");
+ }
+
+ // Initialize TransposeParams
+ nnfw::cker::TransposeParams transpose_param;
+ transpose_param.perm_count = 2;
+ transpose_param.perm[0] = 1;
+ transpose_param.perm[1] = 0;
+
+ // Initialize FullyConnectedParams
+ nnfw::cker::FullyConnectedParams op_params;
+ float output_activation_min = 0;
+ float output_activation_max = 0;
+ CalculateActivationRange(ir::Activation::NONE, &output_activation_min, &output_activation_max);
+ op_params.activation = nnfw::cker::FusedActivationFunctionType::kNone;
+ op_params.float_activation_min = output_activation_min;
+ op_params.float_activation_max = output_activation_max;
+ op_params.lhs_cacheable = false;
+ op_params.rhs_cacheable = false;
+
+ // Transpose and compute gradient for input
+ // ∂L/∂X = fc(Incoming gradient, transposed W)
+ auto transposed_weights = _transposed_weights.get();
+ assert(transposed_weights->getShape().rank() == 2);
+ nnfw::cker::Transpose(transpose_param, getShape(_weights), getBuffer<float>(_weights),
+ getShape(transposed_weights), getBuffer<float>(transposed_weights));
+
+ nnfw::cker::FullyConnected(op_params, getShape(backprop_act), getBuffer<float>(backprop_act),
+ getShape(transposed_weights), getBuffer<float>(transposed_weights),
+ getShape(nullptr), nullptr, getShape(_deriv_input),
+ getBuffer<float>(_deriv_input));
+
+ // Transpose and compute gradient for weights
+ // ∂L/∂W = fc(transposed incomming gradient, transposed X)
+ auto transposed_input = _transposed_input.get();
+ assert(transposed_input->getShape().rank() == 2);
+ nnfw::cker::Transpose(transpose_param, getShape(_input), getBuffer<float>(_input),
+ getShape(transposed_input), getBuffer<float>(transposed_input));
+
+ auto transposed_deriv_output = _transposed_deriv_output.get();
+ assert(transposed_deriv_output->getShape().rank() == 2);
+ nnfw::cker::Transpose(transpose_param, getShape(backprop_act), getBuffer<float>(backprop_act),
+ getShape(transposed_deriv_output),
+ getBuffer<float>(transposed_deriv_output));
+
+ nnfw::cker::FullyConnected(op_params, getShape(transposed_deriv_output),
+ getBuffer<float>(transposed_deriv_output), getShape(transposed_input),
+ getBuffer<float>(transposed_input), getShape(nullptr), nullptr,
+ getShape(_grad_weights), getBuffer<float>(_grad_weights));
+
+ // Compute gradient for bias
+ if (_bias)
+ {
+ assert(_grad_bias);
+ nnfw::cker::train::FullyConnectedBiasGrad(getShape(backprop_act),
+ getBuffer<float>(backprop_act), getShape(_grad_bias),
+ getBuffer<float>(_grad_bias));
+ }
+}
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/ops/FullyConnectedLayer.h b/runtime/onert/backend/train/ops/FullyConnectedLayer.h
new file mode 100644
index 000000000..1d9b30a23
--- /dev/null
+++ b/runtime/onert/backend/train/ops/FullyConnectedLayer.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_TRAIN_OPS_FULLYCONNECTEDLAYER_H__
+#define __ONERT_BACKEND_TRAIN_OPS_FULLYCONNECTEDLAYER_H__
+
+#include "../ExternalContext.h"
+#include "../Tensor.h"
+
+#include <exec/train/ITrainableFunction.h>
+#include <ops/FullyConnectedLayer.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+class FullyConnectedLayer : public exec::train::ITrainableFunction,
+ public cpu::ops::FullyConnectedLayer
+{
+public:
+ FullyConnectedLayer();
+ ~FullyConnectedLayer();
+
+public:
+ void configure(const IPortableTensor *input, const IPortableTensor *weights,
+ const IPortableTensor *bias, IPortableTensor *output, IPortableTensor *deriv_input,
+ IPortableTensor *grad_weights, IPortableTensor *grad_bias,
+ const IPortableTensor *deriv_output, ir::Activation activation,
+ ir::FullyConnectedWeightsFormat weights_format,
+ const std::shared_ptr<train::ExternalContext> &external_context);
+
+ void forward(bool training) override;
+ void backward() override;
+
+private:
+ void backwardFloat32();
+
+private:
+ IPortableTensor *_grad_weights;
+ IPortableTensor *_grad_bias;
+ IPortableTensor *_deriv_input;
+ const IPortableTensor *_deriv_output;
+
+ // TODO Optimize memory
+ std::unique_ptr<Tensor> _transposed_weights;
+ std::unique_ptr<Tensor> _transposed_input;
+ std::unique_ptr<Tensor> _transposed_deriv_output;
+ std::unique_ptr<Tensor> _act_deriv_output;
+};
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_OPS_FULLYCONNECTEDLAYER_H__
diff --git a/runtime/onert/backend/train/ops/GradientApplier.cc b/runtime/onert/backend/train/ops/GradientApplier.cc
new file mode 100644
index 000000000..90d1bb9d0
--- /dev/null
+++ b/runtime/onert/backend/train/ops/GradientApplier.cc
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GradientApplier.h"
+
+#include <exec/train/optimizer/Optimizer.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+GradientApplier::GradientApplier() : _optimizer{nullptr}, _gradient_tensor{}, _trainable_tensor{}
+{
+ // DO NOTHING
+}
+
+void GradientApplier::configure(std::shared_ptr<exec::train::optimizer::Optimizer> optimizer,
+ const IPortableTensor *gradient, ITrainableTensor *trainable)
+{
+ _optimizer = optimizer;
+ _gradient_tensor = gradient;
+ _trainable_tensor = trainable;
+}
+
+void GradientApplier::applyGradient(uint32_t training_step)
+{
+ _optimizer->applyGradient(
+ std::forward_as_tuple(*_gradient_tensor, *_trainable_tensor, training_step));
+}
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/ops/GradientApplier.h b/runtime/onert/backend/train/ops/GradientApplier.h
new file mode 100644
index 000000000..94234e182
--- /dev/null
+++ b/runtime/onert/backend/train/ops/GradientApplier.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_TRAIN_OPS_GRADIENT_APPLIER_H__
+#define __ONERT_BACKEND_TRAIN_OPS_GRADIENT_APPLIER_H__
+
+#include <exec/train/IGradientApplier.h>
+
+#include <exec/train/optimizer/Optimizer.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+class GradientApplier : public ::onert::exec::train::IGradientApplier
+{
+public:
+ GradientApplier();
+ ~GradientApplier() = default;
+
+ void configure(std::shared_ptr<exec::train::optimizer::Optimizer> optimizer,
+ const IPortableTensor *gradient, ITrainableTensor *trainable);
+ void applyGradient(uint32_t training_step) override;
+
+private:
+ std::shared_ptr<exec::train::optimizer::Optimizer> _optimizer;
+ const IPortableTensor *_gradient_tensor;
+ ITrainableTensor *_trainable_tensor;
+};
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_OPS_GRADIENT_APPLIER_H__
diff --git a/runtime/onert/backend/train/ops/LossLayer.cc b/runtime/onert/backend/train/ops/LossLayer.cc
new file mode 100644
index 000000000..d004722a0
--- /dev/null
+++ b/runtime/onert/backend/train/ops/LossLayer.cc
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "LossLayer.h"
+#include "OperationUtils.h"
+
+#include <cker/train/operation/Loss.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+LossLayer::LossLayer()
+ : _y_pred(nullptr), _y_true(nullptr), _output(nullptr), _deriv_y_pred(nullptr),
+ _loss_type(LossType::kMSE)
+{
+ // DO NOTHING
+}
+
+void LossLayer::configure(const IPortableTensor *y_pred, const IPortableTensor *y_true,
+ IPortableTensor *output, IPortableTensor *deriv_y_pred,
+ LossType loss_type)
+{
+ assert(y_pred != nullptr);
+ assert(y_true != nullptr);
+ assert(output != nullptr);
+ assert(deriv_y_pred != nullptr);
+ switch (loss_type)
+ {
+ case LossType::kMSE:
+ break;
+ default:
+ throw std::runtime_error("LossLayer: unsupported loss type");
+ }
+
+ _y_pred = y_pred;
+ _y_true = y_true;
+ _output = output;
+ _deriv_y_pred = deriv_y_pred;
+ _loss_type = loss_type;
+}
+
+void LossLayer::forward(bool)
+{
+ // TODO Implement this
+ switch (_loss_type)
+ {
+ case LossType::kMSE:
+ if (_y_pred->data_type() == OperandType::FLOAT32)
+ {
+ nnfw::cker::train::MSE(getShape(_y_pred), getBuffer<float>(_y_pred), getShape(_y_true),
+ getBuffer<float>(_y_true), getShape(_output),
+ getBuffer<float>(_output));
+ }
+ break;
+ default:
+ throw std::runtime_error("LossLayer: unsupported loss type");
+ }
+}
+
+void LossLayer::backward()
+{
+ switch (_loss_type)
+ {
+ case LossType::kMSE:
+ if (_y_pred->data_type() == OperandType::FLOAT32)
+ {
+ nnfw::cker::train::MSEGrad(getShape(_y_pred), getBuffer<float>(_y_pred), getShape(_y_true),
+ getBuffer<float>(_y_true), getShape(_deriv_y_pred),
+ getBuffer<float>(_deriv_y_pred));
+ }
+ break;
+ default:
+ throw std::runtime_error("LossLayer: unsupported loss type");
+ }
+}
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/ops/LossLayer.h b/runtime/onert/backend/train/ops/LossLayer.h
new file mode 100644
index 000000000..18c6b315b
--- /dev/null
+++ b/runtime/onert/backend/train/ops/LossLayer.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_TRAIN_OPS_LOSSLAYER_H__
+#define __ONERT_BACKEND_TRAIN_OPS_LOSSLAYER_H__
+
+#include <backend/IPortableTensor.h>
+#include <ops/ElementwiseActivationLayer.h>
+
+#include <exec/train/ITrainableFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+enum class LossType
+{
+ kMSE,
+};
+
+class LossLayer : public ::onert::exec::train::ITrainableFunction
+{
+public:
+ LossLayer();
+
+ void configure(const IPortableTensor *y_pred, const IPortableTensor *y_true,
+ IPortableTensor *output, IPortableTensor *deriv_y_pred, LossType loss_type);
+ void forward(bool training) override;
+ void backward() override;
+
+private:
+ const IPortableTensor *_y_pred;
+ const IPortableTensor *_y_true;
+ IPortableTensor *_output;
+ IPortableTensor *_deriv_y_pred;
+ LossType _loss_type;
+};
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_OPS_LOSSLAYER_H__
diff --git a/runtime/onert/backend/train/ops/OperationUtils.h b/runtime/onert/backend/train/ops/OperationUtils.h
new file mode 100644
index 000000000..fe0a02340
--- /dev/null
+++ b/runtime/onert/backend/train/ops/OperationUtils.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_TRAIN_OPS_OPERATION_UTILS_H__
+#define __ONERT_BACKEND_TRAIN_OPS_OPERATION_UTILS_H__
+
+#include <ops/OperationUtils.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+using OperandType = onert::ir::DataType;
+using cpu::ops::getBuffer;
+using cpu::ops::getShape;
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_OPS_OPERATION_UTILS_H__
diff --git a/runtime/onert/backend/train/ops/PoolLayer.cc b/runtime/onert/backend/train/ops/PoolLayer.cc
new file mode 100644
index 000000000..c8a8422aa
--- /dev/null
+++ b/runtime/onert/backend/train/ops/PoolLayer.cc
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PoolLayer.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+PoolLayer::PoolLayer() : cpu::ops::PoolLayer()
+{
+ // DO NOTHING
+}
+
+void PoolLayer::configure(const IPortableTensor *input, const uint32_t paddingLeft,
+ const uint32_t paddingRight, const uint32_t paddingTop,
+ const uint32_t paddingBottom, const uint32_t strideWidth,
+ const uint32_t strideHeight, const uint32_t kernelWidth,
+ const uint32_t kernelHeight, const ir::Activation activation,
+ IPortableTensor *output, const PoolType op_type)
+{
+ switch (op_type)
+ {
+ case PoolType::kMax:
+ cpu::ops::PoolLayer::configure(input, paddingLeft, paddingRight, paddingTop, paddingBottom,
+ strideWidth, strideHeight, kernelWidth, kernelHeight,
+ activation, output, cpu::ops::PoolType::kMax);
+ break;
+ default:
+ throw std::runtime_error("PoolLayer: Unsupported pool type");
+ }
+}
+
+void PoolLayer::forward(bool training)
+{
+ if (training)
+ {
+ // TODO Implement training pool layer
+ }
+ else
+ {
+ cpu::ops::PoolLayer::run();
+ }
+}
+
+void PoolLayer::backward()
+{
+ // TODO Implement detail
+}
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/ops/PoolLayer.h b/runtime/onert/backend/train/ops/PoolLayer.h
new file mode 100644
index 000000000..7f93b4a97
--- /dev/null
+++ b/runtime/onert/backend/train/ops/PoolLayer.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_TRAIN_OPS_POOLLAYER_H__
+#define __ONERT_BACKEND_TRAIN_OPS_POOLLAYER_H__
+
+#include <ops/PoolLayer.h>
+
+#include <exec/train/ITrainableFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+enum class PoolType
+{
+ kMax,
+};
+
+class PoolLayer : public ::onert::exec::train::ITrainableFunction, public cpu::ops::PoolLayer
+{
+public:
+ PoolLayer();
+
+public:
+ void configure(const IPortableTensor *input, const uint32_t paddingLeft,
+ const uint32_t paddingRight, const uint32_t paddingTop,
+ const uint32_t paddingBottom, const uint32_t strideWidth,
+ const uint32_t strideHeight, const uint32_t kernelWidth,
+ const uint32_t kernelHeight, const ir::Activation activation,
+ IPortableTensor *output, const PoolType op_type);
+ void forward(bool training) override;
+ void backward() override;
+};
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_OPS_POOLLAYER_H__
diff --git a/runtime/onert/backend/train/ops/ReshapeLayer.cc b/runtime/onert/backend/train/ops/ReshapeLayer.cc
new file mode 100644
index 000000000..1716174a9
--- /dev/null
+++ b/runtime/onert/backend/train/ops/ReshapeLayer.cc
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ReshapeLayer.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+ReshapeLayer::ReshapeLayer()
+ : _input{nullptr}, _shape{nullptr}, _output{nullptr}, _deriv_input{nullptr}, _deriv_output{
+ nullptr}
+{
+ // DO NOTHING
+}
+
+void ReshapeLayer::reshapeGeneric(const IPortableTensor *input, IPortableTensor *output)
+{
+ size_t count = input->total_size();
+ memcpy(output->buffer(), input->buffer(), count);
+}
+
+void ReshapeLayer::configure(const IPortableTensor *input, const IPortableTensor *shape,
+ IPortableTensor *output, IPortableTensor *deriv_input,
+ const IPortableTensor *deriv_output)
+{
+ _input = input;
+ /* note : shape is optional. If not provided from model, _shape is nullptr. */
+ _shape = shape;
+ _output = output;
+
+ _deriv_input = deriv_input;
+ _deriv_output = deriv_output;
+}
+
+void ReshapeLayer::forward(bool) { reshapeGeneric(_input, _output); }
+
+void ReshapeLayer::backward() { reshapeGeneric(_deriv_output, _deriv_input); }
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/ops/ReshapeLayer.h b/runtime/onert/backend/train/ops/ReshapeLayer.h
new file mode 100644
index 000000000..e4f017225
--- /dev/null
+++ b/runtime/onert/backend/train/ops/ReshapeLayer.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_TRAIN_OPS_RESHAPELAYER_H__
+#define __ONERT_BACKEND_TRAIN_OPS_RESHAPELAYER_H__
+
+#include <backend/IPortableTensor.h>
+
+#include <exec/train/ITrainableFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+class ReshapeLayer : public ::onert::exec::train::ITrainableFunction
+{
+public:
+ ReshapeLayer();
+
+public:
+ void configure(const IPortableTensor *input, const IPortableTensor *shape,
+ IPortableTensor *output, IPortableTensor *deriv_input,
+ const IPortableTensor *deriv_output);
+ void forward(bool training) override;
+ void backward() override;
+
+private:
+ void reshapeGeneric(const IPortableTensor *input, IPortableTensor *output);
+
+private:
+ const IPortableTensor *_input;
+ const IPortableTensor *_shape;
+ IPortableTensor *_output;
+
+ IPortableTensor *_deriv_input;
+ const IPortableTensor *_deriv_output;
+};
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_OPS_RESHAPELAYER_H__
diff --git a/runtime/onert/backend/train/train.cc b/runtime/onert/backend/train/train.cc
new file mode 100644
index 000000000..a77f71c43
--- /dev/null
+++ b/runtime/onert/backend/train/train.cc
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Backend.h"
+
+extern "C" {
+
+onert::backend::Backend *onert_backend_create() { return new onert::backend::train::Backend; }
+
+void onert_backend_destroy(onert::backend::Backend *backend) { delete backend; }
+}
diff --git a/runtime/onert/backend/trix/BackendContext.cc b/runtime/onert/backend/trix/BackendContext.cc
index 39048f2be..51571b458 100644
--- a/runtime/onert/backend/trix/BackendContext.cc
+++ b/runtime/onert/backend/trix/BackendContext.cc
@@ -37,7 +37,7 @@ FunctionMap BackendContext::genKernels()
{
FunctionMap ret;
- for (auto op_ind : _data.op_order)
+ for (auto &&op_ind : _data.op_order)
{
auto fn_seq = kernel_gen->generate(op_ind);
ret.emplace_back(op_ind, std::move(fn_seq));
diff --git a/runtime/onert/backend/trix/Config.cc b/runtime/onert/backend/trix/Config.cc
index c23326423..b536fd58c 100644
--- a/runtime/onert/backend/trix/Config.cc
+++ b/runtime/onert/backend/trix/Config.cc
@@ -25,7 +25,7 @@ namespace trix
bool Config::initialize() { return true; }
-ir::Layout Config::supportLayout(const ir::Operation &, ir::Layout) { return ir::Layout::NHWC; }
+ir::Layout Config::supportLayout(const ir::IOperation &, ir::Layout) { return ir::Layout::NHWC; }
} // namespace trix
} // namespace backend
diff --git a/runtime/onert/backend/trix/Config.h b/runtime/onert/backend/trix/Config.h
index 799047d6f..310c57b29 100644
--- a/runtime/onert/backend/trix/Config.h
+++ b/runtime/onert/backend/trix/Config.h
@@ -33,7 +33,7 @@ class Config : public IConfig
public:
std::string id() override { return "trix"; }
bool initialize() override;
- ir::Layout supportLayout(const ir::Operation &node, ir::Layout frontend_layout) override;
+ ir::Layout supportLayout(const ir::IOperation &node, ir::Layout frontend_layout) override;
bool supportPermutation() override { return true; }
bool supportDynamicTensor() override { return false; }
bool supportFP16() override { return false; }
diff --git a/runtime/onert/backend/trix/DevContext.cc b/runtime/onert/backend/trix/DevContext.cc
index 059514878..4d58a7d9f 100644
--- a/runtime/onert/backend/trix/DevContext.cc
+++ b/runtime/onert/backend/trix/DevContext.cc
@@ -71,7 +71,13 @@ DevContext::~DevContext()
ModelID DevContext::registerModel(const std::string &model_file_path)
{
- auto meta = getNPUmodel_metadata(model_file_path.c_str(), false);
+ if (_dev_handles.size() == 0)
+ {
+ throw std::runtime_error("No npu device is available");
+ }
+
+ std::unique_ptr<npubin_meta, decltype(&free)> meta(
+ getNPUmodel_metadata(model_file_path.c_str(), false), free);
if (meta == nullptr)
{
@@ -83,7 +89,7 @@ ModelID DevContext::registerModel(const std::string &model_file_path)
file_info.filepath = model_file_path.c_str();
file_info.size = meta->size;
- ModelID model_id;
+ ModelID model_id = 0;
for (uint32_t dev_num = 0; dev_num < _dev_handles.size(); ++dev_num)
{
@@ -97,7 +103,7 @@ ModelID DevContext::registerModel(const std::string &model_file_path)
if (dev_num == 0)
{
model_id = model_id_at_device;
- _meta_map[model_id_at_device] = std::shared_ptr<npubin_meta>(meta);
+ _meta_map[model_id_at_device] = std::shared_ptr<npubin_meta>(std::move(meta));
}
else
{
diff --git a/runtime/onert/backend/xnnpack/BackendContext.cc b/runtime/onert/backend/xnnpack/BackendContext.cc
index c52e275aa..b555a4ac6 100644
--- a/runtime/onert/backend/xnnpack/BackendContext.cc
+++ b/runtime/onert/backend/xnnpack/BackendContext.cc
@@ -37,7 +37,7 @@ FunctionMap BackendContext::genKernels()
{
FunctionMap ret;
- for (auto op_ind : _data.op_order)
+ for (auto &&op_ind : _data.op_order)
{
auto fn_seq = kernel_gen->generate(op_ind);
ret.emplace_back(op_ind, std::move(fn_seq));
diff --git a/runtime/onert/backend/xnnpack/Config.cc b/runtime/onert/backend/xnnpack/Config.cc
index 8783ff390..cc27f717f 100644
--- a/runtime/onert/backend/xnnpack/Config.cc
+++ b/runtime/onert/backend/xnnpack/Config.cc
@@ -37,7 +37,7 @@ bool Config::initialize()
return true;
}
-ir::Layout Config::supportLayout(const ir::Operation &, ir::Layout) { return ir::Layout::NHWC; }
+ir::Layout Config::supportLayout(const ir::IOperation &, ir::Layout) { return ir::Layout::NHWC; }
} // namespace xnnpack
} // namespace backend
diff --git a/runtime/onert/backend/xnnpack/Config.h b/runtime/onert/backend/xnnpack/Config.h
index 2cf7406e5..4c5fba587 100644
--- a/runtime/onert/backend/xnnpack/Config.h
+++ b/runtime/onert/backend/xnnpack/Config.h
@@ -36,7 +36,7 @@ public:
public:
std::string id() override { return "xnnpack"; }
bool initialize() override;
- ir::Layout supportLayout(const ir::Operation &node, ir::Layout frontend_layout) override;
+ ir::Layout supportLayout(const ir::IOperation &node, ir::Layout frontend_layout) override;
bool supportPermutation() override { return true; }
bool supportDynamicTensor() override { return true; }
bool supportFP16() override { return false; }
diff --git a/runtime/onert/backend/xnnpack/KernelGenerator.cc b/runtime/onert/backend/xnnpack/KernelGenerator.cc
index 9580bec8c..25f3fd238 100644
--- a/runtime/onert/backend/xnnpack/KernelGenerator.cc
+++ b/runtime/onert/backend/xnnpack/KernelGenerator.cc
@@ -69,7 +69,7 @@ std::unique_ptr<exec::FunctionSequence> KernelGenerator::generate(ir::OperationI
assert(_return_fn); // _return_fn must have been generated
ret->append(std::move(_return_fn));
- for (auto ind : (op.getInputs() | ir::Remove::UNDEFINED) + op.getOutputs())
+ for (auto &&ind : (op.getInputs() | ir::Remove::UNDEFINED) + op.getOutputs())
{
auto portable_tensor = _tensor_reg->getPortableTensor(ind);
if (portable_tensor)
diff --git a/runtime/onert/core/CMakeLists.txt b/runtime/onert/core/CMakeLists.txt
index 8041ab5bc..8ff3fdf42 100644
--- a/runtime/onert/core/CMakeLists.txt
+++ b/runtime/onert/core/CMakeLists.txt
@@ -2,7 +2,19 @@ file(GLOB_RECURSE SOURCES "src/*.cc")
file(GLOB_RECURSE TESTS "*.test.cc")
list(REMOVE_ITEM SOURCES ${TESTS})
-nnfw_find_package(Ruy REQUIRED)
+if(NOT BUILD_MINMAX_H5DUMPER)
+ file(GLOB_RECURSE SRC_TO_REMOVE "src/dumper/h5/*.cc")
+ list(REMOVE_ITEM SOURCES ${SRC_TO_REMOVE})
+ file(GLOB_RECURSE SRC_TO_REMOVE "src/exec/MinMaxRecorder.cc")
+ list(REMOVE_ITEM SOURCES ${SRC_TO_REMOVE})
+endif(NOT BUILD_MINMAX_H5DUMPER)
+
+if(NOT ENABLE_ONERT_TRAIN)
+ file(GLOB_RECURSE SRC_TRAIN "src/*/train/*.cc")
+ list(REMOVE_ITEM SOURCES ${SRC_TRAIN})
+ file(GLOB_RECURSE SRC_TRAIN "src/*/*/train/*.cc")
+ list(REMOVE_ITEM SOURCES ${SRC_TRAIN})
+endif(NOT ENABLE_ONERT_TRAIN)
add_library(onert_core SHARED ${SOURCES})
set_target_properties(onert_core PROPERTIES POSITION_INDEPENDENT_CODE ON)
@@ -18,9 +30,26 @@ target_link_libraries(onert_core PRIVATE nnfw_lib_misc nnfw_lib_cker)
target_link_libraries(onert_core PRIVATE nnfw_common)
target_link_libraries(onert_core PRIVATE nnfw_coverage)
target_link_libraries(onert_core PRIVATE dl ${LIB_PTHREAD})
+
+# Ruy
+nnfw_find_package(Ruy REQUIRED)
target_link_libraries(onert_core PRIVATE ruy)
target_link_libraries(onert_core INTERFACE ruy_instrumentation)
+# H5 Minmax Dumper
+if(BUILD_MINMAX_H5DUMPER)
+ nnfw_find_package(HDF5 REQUIRED)
+ target_compile_definitions(onert_core PRIVATE MINMAX_H5DUMPER=1)
+ target_include_directories(onert_core PRIVATE ${HDF5_INCLUDE_DIRS})
+ target_link_libraries(onert_core PRIVATE ${HDF5_CXX_LIBRARIES})
+endif(BUILD_MINMAX_H5DUMPER)
+
+# Training feature
+# Use public to use this flag on all modules and tests
+if(ENABLE_ONERT_TRAIN)
+ target_compile_definitions(onert_core PUBLIC ONERT_TRAIN)
+endif(ENABLE_ONERT_TRAIN)
+
if(CMAKE_BUILD_TYPE_LC STREQUAL "release")
add_custom_command(TARGET onert_core POST_BUILD
COMMAND ${CMAKE_STRIP} "--strip-unneeded" $<TARGET_FILE_NAME:onert_core>)
diff --git a/runtime/onert/core/include/backend/IConfig.h b/runtime/onert/core/include/backend/IConfig.h
index 409fd3d9f..e297c5f1e 100644
--- a/runtime/onert/core/include/backend/IConfig.h
+++ b/runtime/onert/core/include/backend/IConfig.h
@@ -18,7 +18,7 @@
#define __ONERT_BACKEND_ICONFIG_H__
#include "ir/Layout.h"
-#include "ir/Operation.h"
+#include "ir/IOperation.h"
#include "util/ITimer.h"
#include <memory>
@@ -48,11 +48,11 @@ struct IConfig
/**
* @brief Returns supported layout for the given \p node and \p frontend_layout
*
- * @param node Operation
+ * @param node IOperation
* @param frontend_layout The layout defined in the model
* @return ir::Layout The layout that the backend kernel actually uses
*/
- virtual ir::Layout supportLayout(const ir::Operation &node, ir::Layout frontend_layout) = 0;
+ virtual ir::Layout supportLayout(const ir::IOperation &node, ir::Layout frontend_layout) = 0;
/**
* @brief The function that is called after each Operation run on profiling mode.
* This may be useful for profiling GPU-based or special computing units.
diff --git a/runtime/onert/core/include/backend/basic/BackendContextHelpers.h b/runtime/onert/core/include/backend/basic/BackendContextHelpers.h
index 970a9f71c..9992ca140 100644
--- a/runtime/onert/core/include/backend/basic/BackendContextHelpers.h
+++ b/runtime/onert/core/include/backend/basic/BackendContextHelpers.h
@@ -226,13 +226,15 @@ template <typename T_BackendContext> ITensorRegistry *genTensors(T_BackendContex
return ctx.tensor_registry.get();
}
-inline void initConsts(BackendContext &ctx)
+inline void initConsts(const ir::Operands &operands,
+ const util::Set<ir::OperandIndex> &external_operands,
+ ITensorRegistry *tensor_registry)
{
- ctx.graph()->operands().iterate([&](const ir::OperandIndex &ind, const ir::Operand &operand) {
- if (ctx.external_operands().contains(ind) || !operand.isConstant())
+ operands.iterate([&](const ir::OperandIndex &ind, const ir::Operand &operand) {
+ if (external_operands.contains(ind) || !operand.isConstant())
return;
- auto tensor = ctx.tensor_registry->getNativeITensor(ind);
+ auto tensor = tensor_registry->getNativeITensor(ind);
assert(tensor != nullptr);
VERBOSE(FillOperandData) << "Fill data for " << ind << std::endl;
@@ -248,6 +250,11 @@ inline void initConsts(BackendContext &ctx)
});
}
+inline void initConsts(BackendContext &ctx)
+{
+ initConsts(ctx.graph()->operands(), ctx.external_operands(), ctx.tensor_registry.get());
+}
+
} // namespace basic
} // namespace backend
} // namespace onert
diff --git a/runtime/onert/core/include/backend/basic/DynamicTensorManager.h b/runtime/onert/core/include/backend/basic/DynamicTensorManager.h
index 92d8ee3ab..0535dd5e1 100644
--- a/runtime/onert/core/include/backend/basic/DynamicTensorManager.h
+++ b/runtime/onert/core/include/backend/basic/DynamicTensorManager.h
@@ -21,9 +21,11 @@
#include "TensorRegistry.h"
#include <ir/OperandInfo.h>
-#include <ir/Operation.h>
+#include <ir/IOperation.h>
#include <ir/Index.h>
+#include <unordered_set>
+
namespace onert
{
namespace backend
diff --git a/runtime/onert/core/include/backend/basic/StaticTensorManager.h b/runtime/onert/core/include/backend/basic/StaticTensorManager.h
index f35dbdfe4..6088306ec 100644
--- a/runtime/onert/core/include/backend/basic/StaticTensorManager.h
+++ b/runtime/onert/core/include/backend/basic/StaticTensorManager.h
@@ -38,6 +38,8 @@ class StaticTensorManager
public:
StaticTensorManager(const std::shared_ptr<TensorRegistry> &reg,
DynamicTensorManager *dynamic_tensor_manager);
+ StaticTensorManager(const std::shared_ptr<TensorRegistry> &reg, const std::string planner_id,
+ DynamicTensorManager *dynamic_tensor_manager);
virtual ~StaticTensorManager() = default;
void allocateNonconsts(void);
diff --git a/runtime/onert/core/include/backend/basic/TensorBuilder.h b/runtime/onert/core/include/backend/basic/TensorBuilder.h
index a8014e55d..8ea114912 100644
--- a/runtime/onert/core/include/backend/basic/TensorBuilder.h
+++ b/runtime/onert/core/include/backend/basic/TensorBuilder.h
@@ -38,6 +38,7 @@ class TensorBuilder
{
public:
TensorBuilder(const std::shared_ptr<TensorRegistry> &tensor_reg);
+ TensorBuilder(const std::shared_ptr<TensorRegistry> &tensor_reg, const std::string planner_id);
/**
* @brief Register tensor information to allocate on CPU backend
diff --git a/runtime/onert/core/include/backend/basic/train/TrainableBackendContextHelpers.h b/runtime/onert/core/include/backend/basic/train/TrainableBackendContextHelpers.h
new file mode 100644
index 000000000..e1d3b034a
--- /dev/null
+++ b/runtime/onert/core/include/backend/basic/train/TrainableBackendContextHelpers.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_BASIC_TRAIN_TRAINABLE_BACKEND_CONTEXT_HELPERS_H__
+#define __ONERT_BACKEND_BASIC_TRAIN_TRAINABLE_BACKEND_CONTEXT_HELPERS_H__
+
+#include "backend/basic/BackendContextHelpers.h"
+#include "backend/train/TrainableBackendContext.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace basic
+{
+namespace train
+{
+
+// TODO Unify with the above `getTensors()` function in `BackendContextHelpers.h`
+template <typename TensorBuilder>
+ITensorRegistry *genTensors(backend::train::TrainableBackendContext &ctx,
+ const std::shared_ptr<TensorBuilder> &tensor_builder)
+{
+ const auto &tgraph = *ctx.trainable_graph();
+
+ auto model_io =
+ (tgraph.getInputs() + tgraph.getOutputs()) | ir::Remove::UNDEFINED | ir::Remove::DUPLICATED;
+ tgraph.operands().iterate([&](const ir::OperandIndex &ind, const ir::Operand &obj) {
+ if (ctx.external_operands().contains(ind))
+ return;
+ // NOTE Assuming there is no layout changes (Always assume NHWC or UNKNOWN)
+ assert(tgraph.layout() != ir::Layout::NCHW);
+ ir::OperandInfo backend_info{obj.shape(), obj.typeInfo(), obj.info().memAllocType(),
+ obj.isConstant()};
+ tensor_builder->registerTensorInfo(ind, backend_info, ir::Layout::NHWC);
+ });
+
+ // For the executors that does not have fixed linear execution order:
+ // To make tensors never be deallocated, this is a workaround to use static memory planner
+ tgraph.operands().iterate([&](const ir::OperandIndex &ind, const ir::Operand &) {
+ if (tensor_builder->isRegistered(ind))
+ tensor_builder->notifyFirstUse(ind);
+ });
+
+ tensor_builder->allocate();
+
+ return ctx.tensor_registry().get();
+}
+
+} // namespace train
+} // namespace basic
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_BASIC_TRAIN_TRAINABLE_BACKEND_CONTEXT_HELPERS_H__
diff --git a/runtime/onert/core/include/backend/basic/train/TrainableTensor.h b/runtime/onert/core/include/backend/basic/train/TrainableTensor.h
new file mode 100644
index 000000000..e985f2930
--- /dev/null
+++ b/runtime/onert/core/include/backend/basic/train/TrainableTensor.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_BASIC_TRAIN_TRAINABLE_TENSOR_H__
+#define __ONERT_BACKEND_BASIC_TRAIN_TRAINABLE_TENSOR_H__
+
+#include "backend/train/ITrainableTensor.h"
+
+#include "backend/basic/Tensor.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace basic
+{
+namespace train
+{
+
+class TrainableTensor : public backend::train::ITrainableTensor
+{
+public:
+ TrainableTensor() = delete;
+ virtual ~TrainableTensor() = default;
+
+public:
+ TrainableTensor(const ir::OperandInfo &info, const ir::Layout layout)
+ : ITrainableTensor{info}, _tensor{info, layout, nullptr}, _opt_vars{}
+ {
+ // DO NOTHING
+ }
+
+public:
+ /**
+ * @brief Set the Buffer object. This method is called for static and non-const tensor
+ */
+ void setBuffer(uint8_t *buffer) { _tensor.setBuffer(buffer); }
+
+public:
+ uint8_t *buffer() const override { return _tensor.buffer(); }
+ /**
+ * @brief Get dimension by index
+ *
+ * @param index Index to get diemension
+ * @return size_t Dimension at index
+ * @note N : dimension(0)
+ * H : dimension(1)
+ * W : dimension(2)
+ * C : dimension(3)
+ */
+ size_t total_size() const override { return _tensor.total_size(); }
+ size_t calcOffset(const ir::Coordinates &coords) const override
+ {
+ return _tensor.calcOffset(coords);
+ }
+ ir::Layout layout() const override { return _tensor.layout(); }
+ ir::DataType data_type() const override { return _tensor.data_type(); }
+ bool is_constant() const override { return _tensor.is_constant(); }
+ bool is_dynamic() const override { return _tensor.is_dynamic(); }
+ ir::Shape getShape() const override { return _tensor.getShape(); };
+ const ir::OperandInfo &get_info() { return _tensor.get_info(); }
+
+public:
+ std::vector<ITensor *> optVars() override;
+ void appendOptVar(std::unique_ptr<Tensor> opt_var) { _opt_vars.emplace_back(std::move(opt_var)); }
+
+public:
+ void fillBuffer(const std::shared_ptr<ir::Data> &data);
+
+private:
+ using ITensor::setShape;
+ using ITensor::set_dynamic;
+ using ITensor::applyShape;
+
+protected:
+ Tensor _tensor;
+ std::vector<std::unique_ptr<Tensor>> _opt_vars; //< Optimizer variables
+};
+
+} // namespace train
+} // namespace basic
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_BASIC_TRAIN_TRAINABLE_TENSOR_H__
diff --git a/runtime/onert/core/include/backend/train/ITensorRegistry.h b/runtime/onert/core/include/backend/train/ITensorRegistry.h
new file mode 100644
index 000000000..72b8a35db
--- /dev/null
+++ b/runtime/onert/core/include/backend/train/ITensorRegistry.h
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_TRAIN_ITENSOR_REGISTRY_H__
+#define __ONERT_BACKEND_TRAIN_ITENSOR_REGISTRY_H__
+
+#include "backend/ITensorRegistry.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+class ITensorRegistry : public backend::ITensorRegistry
+{
+public:
+ /**
+ * @brief Returns pointer of ITensor among native and migrant tensors, not derivative and gradient
+ *
+ */
+ using backend::ITensorRegistry::getITensor;
+
+ /**
+ * @brief Returns pointer of ITensor among native tensors, not derivative and gradient
+ *
+ */
+ using backend::ITensorRegistry::getNativeITensor;
+
+ /**
+ * @brief Returns pointer of ITensor for derivative
+ *
+ * @note Return tensor cannot be used longer than dynamic tensor manager
+ */
+ virtual ITensor *getDerivativeITensor(const ir::OperandIndex &) = 0;
+
+ /**
+ * @brief Returns pointer of ITensor for gradient
+ *
+ * @note Returned tensor cannot be used longer than dynamic tensor manager
+ */
+ virtual ITensor *getGradientITensor(const ir::OperandIndex &) = 0;
+};
+
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+template <typename Tensor, typename TrainableTensor, typename DerivativeTensor,
+ typename GradientTensor>
+class PortableTensorRegistryTemplate : public backend::train::ITensorRegistry
+{
+public:
+ using TrainingTensors = std::tuple<TrainableTensor *, GradientTensor *>;
+
+public:
+ ITensor *getITensor(const ir::OperandIndex &index) override
+ {
+ auto _migrant_tensor = _migrant.find(index);
+ if (_migrant_tensor != _migrant.end())
+ return _migrant_tensor->second;
+ return getNativeITensor(index);
+ }
+
+ ITensor *getNativeITensor(const ir::OperandIndex &index) override
+ {
+ ITensor *tensor = getTrainableTensor(index);
+ if (tensor == nullptr)
+ tensor = getNonConstTensor(index);
+ return tensor;
+ }
+
+ ITensor *getDerivativeITensor(const ir::OperandIndex &index) override
+ {
+ return getDerivativeTensor(index);
+ }
+
+ ITensor *getGradientITensor(const ir::OperandIndex &index) override
+ {
+ return getGradientTensor(index);
+ }
+
+ IPortableTensor *getPortableTensor(const ir::OperandIndex &index)
+ {
+ auto tensor = _trainable.find(index);
+ if (tensor != _trainable.end())
+ {
+ if (tensor->second)
+ return tensor->second.get();
+ }
+ return getNonConstTensor(index);
+ }
+
+ Tensor *getNonConstTensor(const ir::OperandIndex &index)
+ {
+ auto tensor = _non_const.find(index);
+ if (tensor != _non_const.end())
+ return tensor->second.get();
+ return nullptr;
+ }
+
+ TrainableTensor *getTrainableTensor(const ir::OperandIndex &index)
+ {
+ auto tensor = _trainable.find(index);
+ if (tensor != _trainable.end())
+ return tensor->second.get();
+
+ return nullptr;
+ }
+
+ DerivativeTensor *getDerivativeTensor(const ir::OperandIndex &index)
+ {
+ auto tensor = _derivative.find(index);
+ if (tensor != _derivative.end())
+ return tensor->second.get();
+ return nullptr;
+ }
+
+ GradientTensor *getGradientTensor(const ir::OperandIndex &index)
+ {
+ auto tensor = _gradient.find(index);
+ if (tensor != _gradient.end())
+ return tensor->second.get();
+ return nullptr;
+ }
+
+ TrainingTensors getTrainingTensors(const ir::OperandIndex &index)
+ {
+ auto trainable = getTrainableTensor(index);
+ if (trainable == nullptr)
+ throw std::runtime_error{
+ "Tried to get a trainable tensor but the corresponding tensor does not exist."};
+
+ auto gradient = getGradientTensor(index);
+ if (gradient == nullptr)
+ throw std::runtime_error{
+ "Tried to get a gradient tensor but the corresponding tensor does not exist."};
+
+ return TrainingTensors{std::make_pair(trainable, gradient)};
+ }
+
+ bool setMigrantTensor(const ir::OperandIndex &index, IPortableTensor *tensor) override
+ {
+ assert(tensor != nullptr);
+ if (getITensor(index) != nullptr)
+ throw std::runtime_error{
+ "Tried to set a trainable tensor but another tensor already exists."};
+
+ _migrant[index] = tensor;
+ return true;
+ }
+
+ void setNonConstTensor(const ir::OperandIndex &index, std::unique_ptr<Tensor> tensor)
+ {
+ assert(tensor != nullptr);
+ if (getITensor(index) != nullptr)
+ throw std::runtime_error{
+ "Tried to set a trainable tensor but another tensor already exists."};
+
+ _non_const[index] = std::move(tensor);
+ }
+
+ void setTrainableTensor(const ir::OperandIndex &index, std::unique_ptr<TrainableTensor> tensor)
+ {
+ assert(tensor != nullptr);
+ if (getITensor(index) != nullptr)
+ throw std::runtime_error{
+ "Tried to set a trainable tensor but another tensor already exists."};
+
+ _trainable[index] = std::move(tensor);
+ }
+
+ void setDerivativeTensor(const ir::OperandIndex &index, std::unique_ptr<DerivativeTensor> tensor)
+ {
+ assert(tensor != nullptr);
+ auto itr = _derivative.find(index);
+ if (itr != _derivative.end())
+ throw std::runtime_error{
+ "Tried to set a derivative tensor but another derivative tensor already exists."};
+
+ _derivative[index] = std::move(tensor);
+ }
+
+ void setGradientTensor(const ir::OperandIndex &index, std::unique_ptr<GradientTensor> tensor)
+ {
+ assert(tensor != nullptr);
+ auto itr = _gradient.find(index);
+ if (itr != _gradient.end())
+ throw std::runtime_error{
+ "Tried to set a gradient tensor but another gradient tensor already exists."};
+
+ _gradient[index] = std::move(tensor);
+ }
+
+ const ir::OperandIndexMap<std::unique_ptr<TrainableTensor>> &trainable_tensors()
+ {
+ return _trainable;
+ }
+ const ir::OperandIndexMap<std::unique_ptr<Tensor>> &nonconst_tensors() { return _non_const; }
+ const ir::OperandIndexMap<std::unique_ptr<Tensor>> &derivative_tensors() { return _derivative; }
+ const ir::OperandIndexMap<std::unique_ptr<GradientTensor>> &gradient_tensors()
+ {
+ return _gradient;
+ }
+
+private:
+ // Native tensors
+ ir::OperandIndexMap<std::unique_ptr<Tensor>> _non_const;
+ ir::OperandIndexMap<std::unique_ptr<TrainableTensor>> _trainable;
+
+ // Migrant tensors
+ ir::OperandIndexMap<IPortableTensor *> _migrant;
+
+ // Tensors for backpropagation
+ ir::OperandIndexMap<std::unique_ptr<DerivativeTensor>> _derivative;
+
+ // Tensors for updating trainable tensors
+ ir::OperandIndexMap<std::unique_ptr<GradientTensor>> _gradient;
+};
+
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_ITENSOR_REGISTRY_H__
diff --git a/runtime/onert/core/include/backend/train/ITrainableBackend.h b/runtime/onert/core/include/backend/train/ITrainableBackend.h
new file mode 100644
index 000000000..76e394216
--- /dev/null
+++ b/runtime/onert/core/include/backend/train/ITrainableBackend.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_TRAIN_ITRAINABLE_BACKEND_H__
+#define __ONERT_BACKEND_TRAIN_ITRAINABLE_BACKEND_H__
+
+#include <memory>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+class TrainableBackendContext;
+struct TrainableContextData;
+
+struct ITrainableBackend
+{
+ virtual ~ITrainableBackend() = default;
+ virtual std::unique_ptr<TrainableBackendContext> newContext(TrainableContextData &&) const = 0;
+};
+
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_ITRAINABLE_BACKEND_H__
diff --git a/runtime/onert/core/include/backend/train/ITrainableTensor.h b/runtime/onert/core/include/backend/train/ITrainableTensor.h
new file mode 100644
index 000000000..9d7ab345b
--- /dev/null
+++ b/runtime/onert/core/include/backend/train/ITrainableTensor.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_TRAIN_ITRAINABLE_TENSOR_H__
+#define __ONERT_BACKEND_TRAIN_ITRAINABLE_TENSOR_H__
+
+#include "backend/IPortableTensor.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+/**
+ * @brief A tensor class that can be trained
+ *
+ */
+// NOTE It is more appropriate to inherit ITensor, but there is no easy way
+// except for virtual inheritance.
+class ITrainableTensor : public IPortableTensor
+{
+public:
+ using IPortableTensor::IPortableTensor;
+ virtual ~ITrainableTensor() = default;
+
+ /**
+ * @brief Get optimizer variables of this trainable tensor
+ *
+ * @return Optimizer variables
+ */
+ virtual std::vector<ITensor *> optVars() = 0;
+};
+
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_ITRAINABLE_TENSOR_H__
diff --git a/runtime/onert/core/include/backend/train/KernelGeneratorBase.h b/runtime/onert/core/include/backend/train/KernelGeneratorBase.h
new file mode 100644
index 000000000..b5031a5cd
--- /dev/null
+++ b/runtime/onert/core/include/backend/train/KernelGeneratorBase.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_TRAIN_KERNEL_GENERATOR_BASE_H__
+#define __ONERT_BACKEND_TRAIN_KERNEL_GENERATOR_BASE_H__
+
+#include <memory>
+
+#include "backend/ITensorRegistry.h"
+#include "exec/train/TrainableFnSequence.h"
+#include "ir/train/TrainableGraph.h"
+#include "ir/train/TrainableOperationVisitor.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+class KernelGeneratorBase : public ir::train::TrainableOperationVisitor
+{
+public:
+ virtual ~KernelGeneratorBase() = default;
+ KernelGeneratorBase(const ir::train::TrainableGraph &tgraph) : _tgraph{tgraph} {}
+
+ virtual std::unique_ptr<exec::train::TrainableFnSequence> generate(ir::OperationIndex ind) = 0;
+
+protected:
+#define OP(InternalName) \
+ void visit(const ir::train::operation::InternalName &) override \
+ { \
+ throw std::runtime_error("KernelGenerator: NYI for operation '" #InternalName "'"); \
+ }
+#include "ir/train/Operations.lst"
+#undef OP
+
+protected:
+ const ir::train::TrainableGraph &_tgraph;
+ std::unique_ptr<exec::train::ITrainableFunction> _return_fn;
+};
+
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_KERNEL_GENERATOR_BASE_H__
diff --git a/runtime/onert/core/include/backend/train/TrainableBackendContext.h b/runtime/onert/core/include/backend/train/TrainableBackendContext.h
new file mode 100644
index 000000000..3f47af747
--- /dev/null
+++ b/runtime/onert/core/include/backend/train/TrainableBackendContext.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_BACKEND_TRAIN_TRAINABLE_CONTEXT_H__
+#define __ONERT_BACKEND_BACKEND_TRAIN_TRAINABLE_CONTEXT_H__
+
+#include "backend/Backend.h"
+#include "backend/train/ITensorRegistry.h"
+#include "backend/train/ITrainableBackend.h"
+#include "exec/train/optimizer/Optimizer.h"
+#include "exec/train/TrainableFnSequence.h"
+#include "ir/OperandIndexMap.h"
+#include "ir/train/TrainableGraph.h"
+#include "util/Set.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+using FunctionMap =
+ std::vector<std::pair<ir::OperationIndex, std::unique_ptr<exec::train::TrainableFnSequence>>>;
+
+struct TrainableContextData
+{
+ // A partial and trainable graph that only includes used operand/operations of the original graph
+ std::unique_ptr<ir::train::TrainableGraph> tgraph;
+ /* A linear order of operations. This is neccessary for when a graph is not fully connected */
+ std::vector<onert::ir::OperationIndex> op_order;
+ /* Operands that are defined by other backends */
+ util::Set<ir::OperandIndex> external_operands;
+ /* Operand layout info */
+ ir::OperandIndexMap<ir::Layout> operand_layouts;
+ /* Custom kernel builder */
+ std::shared_ptr<custom::IKernelBuilder> custom_kernel_builder;
+ /* Is linear executor or not */
+ bool is_linear_executor;
+ /* Optimizer */
+ std::shared_ptr<exec::train::optimizer::Optimizer> optimizer;
+};
+
+class TrainableBackendContext
+{
+public:
+ TrainableBackendContext(const ITrainableBackend *backend,
+ std::unique_ptr<TrainableContextData> &&tdata,
+ std::shared_ptr<ITensorRegistry> tensor_registry = nullptr)
+ : _backend{backend}, _tdata{std::move(tdata)}, _tensor_registry{tensor_registry}
+ {
+ assert(_tdata);
+ }
+ virtual ~TrainableBackendContext() = default;
+
+ const ir::train::TrainableGraph *trainable_graph() const { return _tdata->tgraph.get(); }
+
+ const TrainableContextData *data() const { return _tdata.get(); }
+
+ const ITrainableBackend *backend() const { return _backend; }
+ const util::Set<ir::OperandIndex> &external_operands() const { return _tdata->external_operands; }
+ const ir::OperandIndexMap<ir::Layout> &operand_layouts() const { return _tdata->operand_layouts; }
+
+ std::shared_ptr<ITensorRegistry> tensor_registry() { return _tensor_registry; }
+
+ virtual ITensorRegistry *genTrainingTensors() = 0;
+ virtual backend::ITensorRegistry *genTensors() = 0;
+ virtual FunctionMap genKernels() = 0;
+
+private:
+ const ITrainableBackend *_backend{nullptr};
+
+protected:
+ std::unique_ptr<TrainableContextData> _tdata;
+
+protected:
+ std::shared_ptr<ITensorRegistry> _tensor_registry;
+};
+
+using TrainableBackendContexts =
+ std::unordered_map<const Backend *, std::unique_ptr<TrainableBackendContext>>;
+
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_BACKEND_TRAIN_TRAINABLE_CONTEXT_H__
diff --git a/runtime/onert/core/include/compiler/CodeMap.h b/runtime/onert/core/include/compiler/CodeMap.h
index b1d861cf8..93fe43cfd 100644
--- a/runtime/onert/core/include/compiler/CodeMap.h
+++ b/runtime/onert/core/include/compiler/CodeMap.h
@@ -19,7 +19,7 @@
#include <unordered_map>
#include "ir/Index.h"
-#include "ir/Operation.h"
+#include "ir/IOperation.h"
#include "exec/FunctionSequence.h"
#include "OperationLowerInfo.h"
@@ -31,11 +31,11 @@ namespace compiler
struct CodeAndInfo
{
ir::OperationIndex op_ind;
- const ir::Operation *op;
+ const ir::IOperation *op;
const OperationLowerInfo *lower_info;
std::unique_ptr<exec::FunctionSequence> fn_seq;
- CodeAndInfo(const ir::OperationIndex op_ind, const ir::Operation *op,
+ CodeAndInfo(const ir::OperationIndex op_ind, const ir::IOperation *op,
const OperationLowerInfo *lower_info,
std::unique_ptr<exec::FunctionSequence> &&fn_seq)
: op_ind{op_ind}, op{op}, lower_info{lower_info}, fn_seq{std::move(fn_seq)}
diff --git a/runtime/onert/core/include/compiler/CompilerFactory.h b/runtime/onert/core/include/compiler/CompilerFactory.h
index 4894366a2..5a8886aa1 100644
--- a/runtime/onert/core/include/compiler/CompilerFactory.h
+++ b/runtime/onert/core/include/compiler/CompilerFactory.h
@@ -19,6 +19,7 @@
#include "ICompiler.h"
#include "CompilerOptions.h"
+#include "compiler/train/TrainingInfo.h"
#include "ir/NNPkg.h"
namespace onert
@@ -34,7 +35,8 @@ public:
public:
std::unique_ptr<ICompiler> create(const std::shared_ptr<ir::NNPkg> &nnpkg,
- std::vector<std::unique_ptr<CompilerOptions>> &copts);
+ std::vector<std::unique_ptr<CompilerOptions>> &copts,
+ const compiler::train::TrainingInfo *training_info = nullptr);
private:
// It is not allowed to use CompilerFactory without get()
diff --git a/runtime/onert/core/include/compiler/CompilerOptions.h b/runtime/onert/core/include/compiler/CompilerOptions.h
index bbe15fc06..bb0d0a430 100644
--- a/runtime/onert/core/include/compiler/CompilerOptions.h
+++ b/runtime/onert/core/include/compiler/CompilerOptions.h
@@ -74,6 +74,7 @@ public:
public:
// GENERAL OPTIONS
std::vector<std::string> backend_list;
+ std::string minmax_filepath; //< File path to save minmax
// OPTIONS ONLY FOR DEBUGGING/PROFILING
std::string trace_filepath; //< File path to save trace records
diff --git a/runtime/onert/core/include/compiler/ILoweredGraph.h b/runtime/onert/core/include/compiler/ILoweredGraph.h
new file mode 100644
index 000000000..bc49fa1d7
--- /dev/null
+++ b/runtime/onert/core/include/compiler/ILoweredGraph.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_COMPILER_ILOWERED_GRAPH_H__
+#define __ONERT_COMPILER_ILOWERED_GRAPH_H__
+
+#include "ir/Graph.h"
+#include "compiler/GraphLowerInfo.h"
+
+namespace onert
+{
+namespace compiler
+{
+
+struct ILoweredGraph
+{
+ virtual ~ILoweredGraph() = default;
+ virtual ir::Graph &graph() = 0;
+ virtual const ir::Graph &graph() const = 0;
+ virtual const compiler::GraphLowerInfo &lower_info() const = 0;
+ virtual compiler::GraphLowerInfo &lower_info() = 0;
+ virtual void setHasDynamicTensor(ir::OperationIndex ind, bool val) = 0;
+ virtual bool getHasDynamicTensor(ir::OperationIndex ind) const = 0;
+};
+
+} // namespace compiler
+} // namespace onert
+
+#endif // __ONERT_COMPILER_ILOWERED_GRAPH_H__
diff --git a/runtime/onert/core/include/compiler/LoweredGraph.h b/runtime/onert/core/include/compiler/LoweredGraph.h
index e9f0ae0de..b970a884b 100644
--- a/runtime/onert/core/include/compiler/LoweredGraph.h
+++ b/runtime/onert/core/include/compiler/LoweredGraph.h
@@ -17,10 +17,11 @@
#ifndef __ONERT_COMPILER_LOWERED_GRAPH_H__
#define __ONERT_COMPILER_LOWERED_GRAPH_H__
-#include "ir/Graph.h"
-#include "compiler/GraphLowerInfo.h"
#include "compiler/BackendResolver.h"
#include "compiler/Compiler.h"
+#include "compiler/GraphLowerInfo.h"
+#include "compiler/ILoweredGraph.h"
+#include "ir/Graph.h"
namespace onert
{
@@ -32,22 +33,22 @@ namespace compiler
* In addition, after lowering, operands in graph will be set to "dynamic"
* if the shape of output of an operation cannot be decided at compilation time.
*/
-class LoweredGraph
+class LoweredGraph : public ILoweredGraph
{
public:
LoweredGraph(const ir::Graph &graph, const compiler::CompilerOptions &options);
- ir::Graph &graph() { return _graph; }
- const ir::Graph &graph() const { return _graph; }
- const compiler::GraphLowerInfo &lower_info() const { return _lower_info_map; }
- compiler::GraphLowerInfo &lower_info() { return _lower_info_map; }
+ ir::Graph &graph() override { return _graph; }
+ const ir::Graph &graph() const override { return _graph; }
+ const compiler::GraphLowerInfo &lower_info() const override { return _lower_info_map; }
+ compiler::GraphLowerInfo &lower_info() override { return _lower_info_map; }
std::shared_ptr<ir::OperationIndexMap<int64_t>> indexed_ranks() { return _indexed_ranks; }
- void setHasDynamicTensor(ir::OperationIndex ind, bool val)
+ void setHasDynamicTensor(ir::OperationIndex ind, bool val) override
{
_has_dynamic_tensor_map.emplace(ind, val);
}
- bool getHasDynamicTensor(ir::OperationIndex ind) const
+ bool getHasDynamicTensor(ir::OperationIndex ind) const override
{
auto itr = _has_dynamic_tensor_map.find(ind);
return (itr == _has_dynamic_tensor_map.end()) ? false : itr->second;
diff --git a/runtime/onert/core/include/compiler/StaticShapeInferer.h b/runtime/onert/core/include/compiler/StaticShapeInferer.h
index 94d6ba1a7..83dede726 100644
--- a/runtime/onert/core/include/compiler/StaticShapeInferer.h
+++ b/runtime/onert/core/include/compiler/StaticShapeInferer.h
@@ -68,7 +68,7 @@ private:
class StaticShapeInferer : public ir::OperationVisitor
{
public:
- StaticShapeInferer(compiler::LoweredGraph *lowered_subg)
+ StaticShapeInferer(compiler::ILoweredGraph *lowered_subg)
: _lowered_subg{lowered_subg}, _subg_input_observers{}, _controlflow_output_observer{nullptr},
_child_inferers{}
{
@@ -102,18 +102,18 @@ public:
void dump();
/**
- * @brief Create a lowered model shape inferer map
- * @param[in] lowered_subgs lowered model subgraph map
+ * @brief Create a shape inferer map for a lowered model
+ * @param[in] lowered_subgs lowered model map
* @return Shape inferer map
*/
static std::unordered_map<ir::SubgraphIndex, std::unique_ptr<StaticShapeInferer>>
createStaticShapeInferers(
- const std::unordered_map<ir::SubgraphIndex, std::unique_ptr<LoweredGraph>> &lowered_subgs);
+ const std::unordered_map<ir::SubgraphIndex, ILoweredGraph *> &lowered_subgs);
private:
- bool checkDynamicInput(const ir::Operation &op);
- bool checkDynamicOutput(const ir::Operation &op);
- void setDynamicOutput(const ir::Operation &op);
+ bool checkDynamicInput(const ir::IOperation &op);
+ bool checkDynamicOutput(const ir::IOperation &op);
+ void setDynamicOutput(const ir::IOperation &op);
private:
// TODO Define visitors for operations. List them in alphabetic order.
@@ -136,6 +136,7 @@ private:
void visit(const ir::operation::Gather &op) override;
void visit(const ir::operation::If &op) override;
void visit(const ir::operation::L2Normalization &op) override;
+ void visit(const ir::operation::Loss &op) override;
void visit(const ir::operation::LSTM &op) override;
void visit(const ir::operation::MatrixBandPart &op) override;
void visit(const ir::operation::OneHot &op) override;
@@ -178,7 +179,7 @@ private:
void handleSimpleUnaryOp(const ir::Operation &op, const ir::OperandIndex input_idx);
private:
- compiler::LoweredGraph *_lowered_subg;
+ compiler::ILoweredGraph *_lowered_subg;
std::unordered_map<ir::SubgraphIndex, std::unique_ptr<OperandObserver>>
_subg_input_observers; // child subg input
std::unique_ptr<OperandObserver> _controlflow_output_observer; // parent controlflow op output
diff --git a/runtime/onert/core/include/compiler/train/LoweredTrainableGraph.h b/runtime/onert/core/include/compiler/train/LoweredTrainableGraph.h
new file mode 100644
index 000000000..a49d1c6a8
--- /dev/null
+++ b/runtime/onert/core/include/compiler/train/LoweredTrainableGraph.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_COMPILER_TRAIN_LOWERED_TRAINABLE_GRAPH_H__
+#define __ONERT_COMPILER_TRAIN_LOWERED_TRAINABLE_GRAPH_H__
+
+#include "compiler/BackendResolver.h"
+#include "compiler/CompilerOptions.h"
+#include "compiler/GraphLowerInfo.h"
+#include "compiler/ILoweredGraph.h"
+#include "ir/train/TrainableGraph.h"
+
+namespace onert
+{
+namespace compiler
+{
+namespace train
+{
+
+// TODO Unify with LoweredGraph
+/**
+ * @brief Class that contains lowering information on graph.
+ * In addition, after lowering, operands in graph will be set to "dynamic"
+ * if the shape of output of an operation cannot be decided at compilation time.
+ */
+class LoweredTrainableGraph : public ILoweredGraph
+{
+public:
+ LoweredTrainableGraph(ir::train::TrainableGraph &graph, const compiler::CompilerOptions &options);
+
+ // TODO Remove const_cast
+ ir::Graph &graph() override { return const_cast<ir::Graph &>(_trainable_graph.graph()); }
+ const ir::Graph &graph() const override { return _trainable_graph.graph(); }
+ ir::train::TrainableGraph &trainable_graph() { return _trainable_graph; }
+ const ir::train::TrainableGraph &trainable_graph() const { return _trainable_graph; }
+ const compiler::GraphLowerInfo &lower_info() const override { return _lower_info_map; }
+ compiler::GraphLowerInfo &lower_info() override { return _lower_info_map; }
+ std::shared_ptr<ir::OperationIndexMap<int64_t>> indexed_ranks() { return _indexed_ranks; }
+
+ void setHasDynamicTensor(ir::OperationIndex, bool has_dynamic) override
+ {
+ if (has_dynamic)
+ throw std::runtime_error("LoweredTrainableGraph does not support dynamic tensors yet");
+ }
+ bool getHasDynamicTensor(ir::OperationIndex) const override { return false; }
+
+private:
+ void makeLowerInfo(const compiler::BackendResolver &backend_resolver);
+ void dumpLowerInfo();
+ void lowerGraph(const compiler::CompilerOptions &options);
+
+private:
+ /**
+ * @brief Copy of target graph for lowering
+ * @note It uses copy of graph, not reference.
+ * It allows the original graph can be compiled multiple times.
+ */
+ ir::train::TrainableGraph _trainable_graph;
+ std::shared_ptr<ir::OperationIndexMap<int64_t>> _indexed_ranks;
+ compiler::GraphLowerInfo _lower_info_map;
+};
+
+} // namespace train
+} // namespace compiler
+} // namespace onert
+
+#endif // __ONERT_COMPILER_TRAIN_LOWERED_TRAINABLE_GRAPH_H__
diff --git a/runtime/onert/core/include/compiler/train/TrainableCodeMap.h b/runtime/onert/core/include/compiler/train/TrainableCodeMap.h
new file mode 100644
index 000000000..1069a47c9
--- /dev/null
+++ b/runtime/onert/core/include/compiler/train/TrainableCodeMap.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_COMPILER_TRAIN_TRAINABLE_CODE_MAP_H__
+#define __ONERT_COMPILER_TRAIN_TRAINABLE_CODE_MAP_H__
+
+#include <unordered_map>
+#include "compiler/OperationLowerInfo.h"
+#include "exec/train/TrainableFnSequence.h"
+#include "ir/train/ITrainableOperation.h"
+
+namespace onert
+{
+namespace compiler
+{
+namespace train
+{
+
+struct TrainableCodeAndInfo
+{
+ ir::OperationIndex op_ind;
+ const ir::train::ITrainableOperation *op;
+ const OperationLowerInfo *lower_info;
+ // TODO Change to TrainableFnSequence
+ std::unique_ptr<exec::train::TrainableFnSequence> tn_seq;
+
+ TrainableCodeAndInfo(const ir::OperationIndex op_ind, const ir::train::ITrainableOperation *op,
+ const OperationLowerInfo *lower_info,
+ std::unique_ptr<exec::train::TrainableFnSequence> &&tn_seq)
+ : op_ind{op_ind}, op{op}, lower_info{lower_info}, tn_seq{std::move(tn_seq)}
+ {
+ }
+};
+
+using TrainableCodeMap = std::unordered_map<ir::OperationIndex, TrainableCodeAndInfo>;
+
+} // namespace train
+} // namespace compiler
+} // namespace onert
+
+#endif // __ONERT_COMPILER_TRAIN_TRAINABLE_CODE_MAP_H__
diff --git a/runtime/onert/core/include/compiler/train/TrainingInfo.h b/runtime/onert/core/include/compiler/train/TrainingInfo.h
new file mode 100644
index 000000000..3b77c838c
--- /dev/null
+++ b/runtime/onert/core/include/compiler/train/TrainingInfo.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_COMPILER_TRAIN_TRAINING_INFO_H__
+#define __ONERT_COMPILER_TRAIN_TRAINING_INFO_H__
+
+#include "ir/Index.h"
+#include "exec/train/optimizer/OptimizerCode.h"
+#include "ir/operation/Loss.h"
+
+namespace onert
+{
+namespace compiler
+{
+namespace train
+{
+
+struct LossInfo
+{
+ ir::operation::Loss::Type type;
+ // TODO Add members for loss
+};
+
+struct OptimizerInfo
+{
+ exec::train::optimizer::OptimizerCode optim_code;
+ float learning_rate;
+ // TODO Add properties
+};
+
+class TrainingInfo
+{
+public:
+ TrainingInfo() {}
+ TrainingInfo(const TrainingInfo &obj) = default;
+ TrainingInfo(TrainingInfo &&) = default;
+ TrainingInfo &operator=(const TrainingInfo &) = default;
+ TrainingInfo &operator=(TrainingInfo &&) = default;
+ ~TrainingInfo() = default;
+
+ uint32_t batchSize() const { return _batch_size; }
+ void setBatchSize(const uint32_t batch_size) { _batch_size = batch_size; }
+ const LossInfo &lossInfo() const { return _loss_info; }
+ void setLossInfo(const LossInfo &loss_info) { _loss_info = loss_info; }
+ const OptimizerInfo &optimizerInfo() const { return _optimizer_info; }
+ void setOptimizerInfo(const OptimizerInfo &optimizer_info) { _optimizer_info = optimizer_info; }
+
+private:
+ LossInfo _loss_info;
+ OptimizerInfo _optimizer_info;
+ uint32_t _batch_size;
+};
+
+} // namespace train
+} // namespace compiler
+} // namespace onert
+
+#endif // __ONERT_COMPILER_TRAIN_TRAINING_INFO_H__
diff --git a/runtime/onert/core/include/exec/Execution.h b/runtime/onert/core/include/exec/Execution.h
index ba3edcdd6..da4d20dbe 100644
--- a/runtime/onert/core/include/exec/Execution.h
+++ b/runtime/onert/core/include/exec/Execution.h
@@ -142,8 +142,28 @@ public:
*/
bool isFinished(void) const;
+#ifdef ONERT_TRAIN
+ /**
+ * @brief Train
+ * @note It should be called after setting input and output buffer
+ * @param training_step The number of iterations of the training process.
+ * In other words, the number of gradient update.
+ */
+ void train(uint32_t training_step);
+
+ /**
+ * @brief Get loss
+ * @note It should be called after training
+ * @param[in] ind Output index
+ * @return @c float Loss value
+ */
+ float getLoss(const ir::IOIndex &ind);
+#endif // ONERT_TRAIN
+
ir::Shape getInputShape(ir::IOIndex ind) const;
ir::Shape getOutputShape(ir::IOIndex ind) const;
+ size_t getInputTotalSize(ir::IOIndex ind) const;
+ size_t getOutputTotalSize(ir::IOIndex ind) const;
private:
const IExecutor *entryExecutor() const { return _executors->entryExecutor(); };
diff --git a/runtime/onert/core/include/exec/FunctionSequence.h b/runtime/onert/core/include/exec/FunctionSequence.h
index a7020d425..f3384be3c 100644
--- a/runtime/onert/core/include/exec/FunctionSequence.h
+++ b/runtime/onert/core/include/exec/FunctionSequence.h
@@ -75,7 +75,7 @@ public:
public: // methods related to dynamic tensor
struct DynamicTensorCtx
{
- const ir::Operation *op = nullptr;
+ const ir::IOperation *op = nullptr;
std::shared_ptr<exec::DynamicShapeInferer> dynamic_shape_inferer = nullptr;
};
diff --git a/runtime/onert/core/include/exec/MinMaxMap.h b/runtime/onert/core/include/exec/MinMaxMap.h
new file mode 100644
index 000000000..fc6849e74
--- /dev/null
+++ b/runtime/onert/core/include/exec/MinMaxMap.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_EXEC_MINMAX_MAP_H__
+#define __ONERT_EXEC_MINMAX_MAP_H__
+
+#include "ir/Index.h"
+#include "util/MinMaxMap.h"
+
+namespace onert
+{
+namespace exec
+{
+struct SMHash
+{
+ size_t operator()(const std::pair<ir::SubgraphIndex, ir::OperationIndex> &k) const noexcept
+ {
+ return std::hash<ir::SubgraphIndex>()(k.first) ^ std::hash<ir::OperationIndex>()(k.second);
+ }
+};
+// SM means single model
+using SMMinMaxMap = util::MinMaxMap<std::pair<ir::SubgraphIndex, ir::OperationIndex>, SMHash>;
+} // namespace exec
+} // namespace onert
+
+#endif // __ONERT_EXEC_MINMAX_MAP_H__
diff --git a/runtime/onert/core/include/exec/train/IGradientApplier.h b/runtime/onert/core/include/exec/train/IGradientApplier.h
new file mode 100644
index 000000000..65e931e0e
--- /dev/null
+++ b/runtime/onert/core/include/exec/train/IGradientApplier.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_EXEC_TRAIN_IGRADIENT_APPLIER_H__
+#define __ONERT_EXEC_TRAIN_IGRADIENT_APPLIER_H__
+
+#include <cstdint>
+
+namespace onert
+{
+namespace exec
+{
+namespace train
+{
+
+class IGradientApplier
+{
+public:
+ virtual ~IGradientApplier() = default;
+
+ /**
+ * @brief Apply gradients to a trainable tensor
+ *
+ * @param training_step The number of iterations of the training process.
+ */
+ virtual void applyGradient(uint32_t training_step) = 0;
+};
+
+} // namespace train
+} // namespace exec
+} // namespace onert
+
+#endif // __ONERT_EXEC_TRAIN_IGRADIENT_APPLIER_H__
diff --git a/runtime/onert/core/include/exec/train/ITrainableFunction.h b/runtime/onert/core/include/exec/train/ITrainableFunction.h
new file mode 100644
index 000000000..45adc258f
--- /dev/null
+++ b/runtime/onert/core/include/exec/train/ITrainableFunction.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_EXEC_TRAIN_I_TRAINABLE_FUNCTION_H__
+#define __ONERT_EXEC_TRAIN_I_TRAINABLE_FUNCTION_H__
+
+#include <cstdint>
+
+namespace onert
+{
+namespace exec
+{
+namespace train
+{
+
+class ITrainableFunction
+{
+public:
+ virtual ~ITrainableFunction() = default;
+ virtual void forward(bool training) = 0;
+ virtual void backward() = 0;
+};
+
+} // namespace train
+} // namespace exec
+} // namespace onert
+
+#endif // __ONERT_EXEC_TRAIN_I_TRAINABLE_FUNCTION_H__
diff --git a/runtime/onert/core/include/exec/train/TrainableFnSequence.h b/runtime/onert/core/include/exec/train/TrainableFnSequence.h
new file mode 100644
index 000000000..8be1b1e5d
--- /dev/null
+++ b/runtime/onert/core/include/exec/train/TrainableFnSequence.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_EXEC_TRAIN_TRAINABLE_FN_SEQUENCE_H__
+#define __ONERT_EXEC_TRAIN_TRAINABLE_FN_SEQUENCE_H__
+
+#include "exec/train/ITrainableFunction.h"
+#include "exec/train/IGradientApplier.h"
+
+#include <memory>
+#include <vector>
+#include <functional>
+
+namespace onert
+{
+namespace exec
+{
+namespace train
+{
+class TrainableFnSequence
+{
+public:
+ void forward(bool training);
+ void backward(uint32_t training_step);
+
+ void append(std::unique_ptr<ITrainableFunction> &&fn);
+ void append(std::unique_ptr<IGradientApplier> &&applier);
+ void iterate(const std::function<void(ITrainableFunction &)> &fn);
+
+public:
+ // TODO Change members
+ std::vector<std::unique_ptr<ITrainableFunction>> _functions;
+ std::vector<std::unique_ptr<IGradientApplier>> _appliers;
+};
+} // namespace train
+} // namespace exec
+} // namespace onert
+
+#endif // __ONERT_EXEC_TRAIN_TRAINABLE_FN_SEQUENCE_H__
diff --git a/runtime/onert/core/include/exec/train/optimizer/Optimizer.h b/runtime/onert/core/include/exec/train/optimizer/Optimizer.h
new file mode 100644
index 000000000..05f2ee19b
--- /dev/null
+++ b/runtime/onert/core/include/exec/train/optimizer/Optimizer.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_EXEC_TRAIN_OPTIMIZER_OPTIMIZER_H__
+#define __ONERT_EXEC_TRAIN_OPTIMIZER_OPTIMIZER_H__
+
+#include "backend/IPortableTensor.h"
+#include "backend/train/ITrainableTensor.h"
+
+#include <string>
+
+namespace onert
+{
+namespace exec
+{
+namespace train
+{
+namespace optimizer
+{
+
+// Gradient tensor, Trainable Tensor, Number of training steps
+using UpdateFactors =
+ std::tuple<const backend::IPortableTensor &, backend::train::ITrainableTensor &, size_t>;
+
+/**
+ * @class Optimizer Base class for optimizers
+ * @brief Base class for all optimizers
+ */
+class Optimizer
+{
+public:
+ virtual ~Optimizer() = default;
+
+ /**
+ * @brief Get the name of optimizer
+ *
+ * @return The name of optimizer
+ */
+ virtual std::string name() const { return std::string{"Invalid"}; }
+
+ /**
+ * @brief Get the Learning Rate
+ *
+ * @param iteration The number of training steps
+ * @return Learning rate
+ */
+ virtual double getLearningRate(uint32_t iteration) const = 0;
+
+ /**
+ * @brief Apply gradient to a trainable tensor
+ *
+ * @param factors UpdateFactors to be used for applying gradient to a trainable tensor
+ */
+ virtual void applyGradient(const UpdateFactors &factors) const = 0;
+
+ // TODO Add member functions for exporting optimizer information
+};
+
+} // namespace optimizer
+} // namespace train
+} // namespace exec
+} // namespace onert
+
+#endif // __ONERT_EXEC_TRAIN_OPTIMIZER_OPTIMIZER_H__
diff --git a/runtime/onert/core/include/exec/train/optimizer/OptimizerCode.h b/runtime/onert/core/include/exec/train/optimizer/OptimizerCode.h
new file mode 100644
index 000000000..3e4a8f2a6
--- /dev/null
+++ b/runtime/onert/core/include/exec/train/optimizer/OptimizerCode.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_EXEC_TRAIN_OPTIMIZER_OPTIMIZER_CODE_H__
+#define __ONERT_EXEC_TRAIN_OPTIMIZER_OPTIMIZER_CODE_H__
+
+#include <functional>
+#include <stdint.h>
+#include <string>
+
+namespace onert
+{
+namespace exec
+{
+namespace train
+{
+namespace optimizer
+{
+
+enum class OptimizerCode
+{
+ Invalid, //< Invalid
+ SGD, //< SGD optimizer
+ Adam //< Adam optimizer
+};
+
+/**
+ * @brief Convert the optimizer code to the name
+ *
+ * @param opcode The optimizer code
+ * @return The name of the optimizer
+ */
+std::string toString(OptimizerCode opcode);
+
+} // namespace optimizer
+} // namespace train
+} // namespace exec
+} // namespace onert
+
+#endif // __ONERT_EXEC_TRAIN_OPTIMIZER_OPTIMIZER_CODE_H__
diff --git a/runtime/onert/core/include/exec/train/optimizer/SGD.h b/runtime/onert/core/include/exec/train/optimizer/SGD.h
new file mode 100644
index 000000000..6a1a5c9b8
--- /dev/null
+++ b/runtime/onert/core/include/exec/train/optimizer/SGD.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_EXEC_TRAIN_OPTIMIZER_SGD_H__
+#define __ONERT_EXEC_TRAIN_OPTIMIZER_SGD_H__
+
+#include "exec/train/optimizer/Optimizer.h"
+
+namespace onert
+{
+namespace exec
+{
+namespace train
+{
+namespace optimizer
+{
+
+/**
+ * @class SGD optimizer class
+ * @brief SGD optimizer
+ */
+class SGD : public Optimizer
+{
+public:
+ struct Property
+ {
+ double momentum{0.0};
+ bool nesterov{false};
+ };
+
+public:
+ explicit SGD() : _props{}, _learning_rate{0.01} {}
+ explicit SGD(const Property &props) : _props{props}, _learning_rate{0.01} {}
+ explicit SGD(double lr) : _props{}, _learning_rate{lr} {}
+ explicit SGD(const Property &props, double lr) : _props{props}, _learning_rate{lr} {}
+
+public:
+ /**
+ * @brief Get the name of optimizer
+ *
+ * @return The name of optimizer
+ */
+ std::string name() const override { return std::string{"SGD"}; }
+
+ /**
+ * @brief Get the Learning Rate
+ *
+ * @param iteration The number of training steps
+ * @return Learning rate
+ */
+ double getLearningRate(uint32_t iteration = 0) const override;
+
+ /**
+ * @brief Apply gradient to a trainable tensor
+ *
+ * @param factors UpdateFactors to be used for applying gradient to a trainable tensor
+ */
+ void applyGradient(const UpdateFactors &factors) const override;
+
+private:
+ Property _props;
+ double _learning_rate;
+};
+
+} // namespace optimizer
+} // namespace train
+} // namespace exec
+} // namespace onert
+
+#endif // __ONERT_EXEC_TRAIN_OPTIMIZER_SGD_H__
diff --git a/runtime/onert/core/include/ir/Graph.h b/runtime/onert/core/include/ir/Graph.h
index 1783cdca0..641698eb2 100644
--- a/runtime/onert/core/include/ir/Graph.h
+++ b/runtime/onert/core/include/ir/Graph.h
@@ -20,27 +20,17 @@
#include <functional>
#include <unordered_map>
+#include "ir/IGraph.h"
#include "ir/Model.h"
#include "ir/Operands.h"
#include "ir/Operations.h"
namespace onert
{
-namespace backend
-{
-namespace custom
-{
-class IKernelBuilder;
-} // namespace custom
-} // namespace backend
-} // namespace onert
-
-namespace onert
-{
namespace ir
{
-class Graph
+class Graph : public IGraph
{
private:
enum class Phase
@@ -70,7 +60,7 @@ public:
* @return OperandIndex @c index if successful, Undefined otherwise
*/
OperandIndex addOperand(OperandIndex index, std::unique_ptr<Operand> &&operand);
- OperationIndex addOperation(std::unique_ptr<Operation> &&node);
+ OperationIndex addOperation(std::unique_ptr<IOperation> &&node);
/**
* @brief Add an operation to the graph with the given index and object
*
@@ -79,52 +69,50 @@ public:
* moved so the caller's pointer will be still valid.
*
* @param index Index to be added
- * @param operation Operation to be added
+ * @param operation IOperation to be added
* @return OperandIndex @c index if successful, Undefined otherwise
*/
- OperationIndex addOperation(OperationIndex index, std::unique_ptr<Operation> &&operation);
+ OperationIndex addOperation(OperationIndex index, std::unique_ptr<IOperation> &&operation);
+ /**
+ * @brief Replace an operation which the graph already has
+ *
+ * If the given @c index is available, it succeeds. And @c operation is moved which invalidates
+ * the caller's pointer. If the given @c operation has at least one invalid operand index, it
+ * fails. And @c operation will not be moved so the caller's pointer will be still valid.
+ *
+ * No information in the graph is changed except for replacing an operation.
+ *
+ * @param operation Operation to be added
+ * @return OperationIndex @c index if successful, UNDEFINED otherwise
+ */
+ OperationIndex replaceOperation(OperationIndex index, std::unique_ptr<IOperation> &&operation);
void setOperandValue(const OperandIndex &ind, std::shared_ptr<Data> data);
+ void changeShape(const OperandIndex &ind, const ir::Shape &new_shape) override;
void addInput(const OperandIndex &ind, const std::string &name = "");
void addOutput(const OperandIndex &ind, const std::string &name = "");
- void verify(void);
+ void verify(void) const;
void removeOperand(const OperandIndex &ind) { _operands.remove(ind); }
void setLayout(Layout layout) { _layout = layout; }
private:
- bool checkOperandsForOperation(const Operation &operation);
- void linkOperandToOperation(OperationIndex index, const Operation &operation);
+ bool checkOperandsForOperation(const IOperation &operation);
+ void linkOperandToOperation(OperationIndex index, const IOperation &operation);
void initializeUseDef();
// TODO Rename to `sweepUnusedOperands`
// TODO Make this public
void sweepGarbageOperands();
- // Custom operations support
-public:
- void
- bindKernelBuilder(const std::shared_ptr<onert::backend::custom::IKernelBuilder> &kernel_builder)
- {
- _kernel_builder = kernel_builder;
- }
-
- const std::shared_ptr<backend::custom::IKernelBuilder> &getKernelBuilder() const
- {
- return _kernel_builder;
- }
-
-private:
- std::shared_ptr<backend::custom::IKernelBuilder> _kernel_builder;
-
// Accessors
public:
- const OperandIndexSequence &getInputs() const { return _inputs; }
+ const OperandIndexSequence &getInputs() const override { return _inputs; }
OperandIndexSequence &getInputs() { return _inputs; }
- const OperandIndexSequence &getOutputs() const { return _outputs; }
+ const OperandIndexSequence &getOutputs() const override { return _outputs; }
OperandIndexSequence &getOutputs() { return _outputs; }
- IOIndex getInputIndex(const std::string &name) const;
- IOIndex getOutputIndex(const std::string &name) const;
- const Operands &operands() const { return _operands; }
+ IOIndex getInputIndex(const std::string &name) const override;
+ IOIndex getOutputIndex(const std::string &name) const override;
+ const Operands &operands() const override { return _operands; }
Operands &operands() { return _operands; } // TODO Remove this non-const accessor
- const Operations &operations() const { return _operations; }
+ const Operations &operations() const override { return _operations; }
Operations &operations() { return _operations; }
Layout layout() const { return _layout; }
diff --git a/runtime/onert/core/include/ir/IGraph.h b/runtime/onert/core/include/ir/IGraph.h
new file mode 100644
index 000000000..34fb20188
--- /dev/null
+++ b/runtime/onert/core/include/ir/IGraph.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_IR_IGRAPH_H__
+#define __ONERT_IR_IGRAPH_H__
+
+#include "ir/Operands.h"
+#include "ir/Operations.h"
+
+namespace onert
+{
+namespace ir
+{
+
+struct IGraph
+{
+ virtual ~IGraph() = default;
+
+ // Accessors
+ virtual const OperandIndexSequence &getInputs() const = 0;
+ virtual const OperandIndexSequence &getOutputs() const = 0;
+ virtual IOIndex getInputIndex(const std::string &name) const = 0;
+ virtual IOIndex getOutputIndex(const std::string &name) const = 0;
+ virtual const Operands &operands() const = 0;
+ virtual const Operations &operations() const = 0;
+
+ // Methods that can change graph
+ virtual void changeShape(const OperandIndex &index, const ir::Shape &new_shape) = 0;
+};
+
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_IGRAPH_H__
diff --git a/runtime/onert/core/include/ir/IOperation.h b/runtime/onert/core/include/ir/IOperation.h
new file mode 100644
index 000000000..be0dd939d
--- /dev/null
+++ b/runtime/onert/core/include/ir/IOperation.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_IR_IOPERATION_H__
+#define __ONERT_IR_IOPERATION_H__
+
+#include <memory>
+
+#include "ir/Index.h"
+#include "ir/OpCode.h"
+#include "ir/OperandIndexSequence.h"
+
+namespace onert
+{
+namespace ir
+{
+
+struct OperationVisitor;
+
+struct IOperation
+{
+ virtual ~IOperation() = default;
+
+ virtual void accept(OperationVisitor &v) const = 0;
+ virtual std::string name() const { return std::string{toString(opcode())}; }
+ virtual OpCode opcode() const = 0;
+
+ virtual void replaceInputs(const OperandIndex &from, const OperandIndex &to) = 0;
+ virtual void replaceOutputs(const OperandIndex &from, const OperandIndex &to) = 0;
+ virtual const OperandIndexSequence &getInputs() const = 0;
+ virtual const OperandIndexSequence &getOutputs() const = 0;
+};
+
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_IOPERATION_H__
diff --git a/runtime/onert/core/include/ir/Model.h b/runtime/onert/core/include/ir/Model.h
index c3c0d87b8..950d28850 100644
--- a/runtime/onert/core/include/ir/Model.h
+++ b/runtime/onert/core/include/ir/Model.h
@@ -20,15 +20,25 @@
#include <memory>
#include <unordered_map>
+#include "ir/IGraph.h"
#include "ir/Index.h"
#include "util/ObjectManager.h"
namespace onert
{
-namespace ir
+namespace backend
+{
+namespace custom
{
+class IKernelBuilder;
+} // namespace custom
+} // namespace backend
+} // namespace onert
-class Graph;
+namespace onert
+{
+namespace ir
+{
class Model
{
@@ -47,7 +57,7 @@ public:
* @param[in] index Index of subgraph to be pushed
* @return Created
*/
- void push(SubgraphIndex index, const std::shared_ptr<Graph> &subg) { _subgraphs[index] = subg; }
+ void push(SubgraphIndex index, const std::shared_ptr<IGraph> &subg) { _subgraphs[index] = subg; }
/**
* @brief Remove the subgraph that is associated with the given index
@@ -61,9 +71,9 @@ public:
* @brief Get the subgraph that is associated with the given index
*
* @param[in] index Index of the subgraph to be returned
- * @return Graph
+ * @return IGraph
*/
- const std::shared_ptr<Graph> &at(const SubgraphIndex &index) const
+ const std::shared_ptr<IGraph> &at(const SubgraphIndex &index) const
{
return _subgraphs.at(index);
}
@@ -71,9 +81,9 @@ public:
* @brief Get the subgraph that is associated with the given index
*
* @param[in] index Index of the subgraph to be returned
- * @return Graph
+ * @return IGraph
*/
- std::shared_ptr<Graph> &at(const SubgraphIndex &index) { return _subgraphs.at(index); }
+ std::shared_ptr<IGraph> &at(const SubgraphIndex &index) { return _subgraphs.at(index); }
/**
* @brief Get the subgraph that is associated with the given index
@@ -93,7 +103,7 @@ public:
* @param[in] fn Function to be run for every container entry
* @return N/A
*/
- void iterate(const std::function<void(const SubgraphIndex &, const Graph &)> &fn) const
+ void iterate(const std::function<void(const SubgraphIndex &, const IGraph &)> &fn) const
{
for (const auto &e : _subgraphs)
{
@@ -107,7 +117,7 @@ public:
* @param[in] fn Function to be run for every container entry
* @return N/A
*/
- void iterate(const std::function<void(const SubgraphIndex &, Graph &)> &fn)
+ void iterate(const std::function<void(const SubgraphIndex &, IGraph &)> &fn)
{
for (const auto &e : _subgraphs)
{
@@ -125,12 +135,46 @@ public:
/**
* @brief Return the primary subgraph
*
- * @return std::shared_ptr<Graph> Primary subgraph
+ * @return std::shared_ptr<IGraph> Primary subgraph
*/
- std::shared_ptr<Graph> primary_subgraph() const { return _subgraphs.at(SubgraphIndex{0}); }
+ std::shared_ptr<IGraph> primary_subgraph() const { return _subgraphs.at(SubgraphIndex{0}); }
+
+ /**
+ * @brief Return whether the model has only typename Graph
+ *
+ * @tparam Graph Type that inherits from IGraph
+ *
+ * @return true if the model has only typename Graph, otherwise false
+ */
+ template <typename Graph, std::enable_if_t<std::is_base_of<IGraph, Graph>::value, bool> = true>
+ bool hasOnly()
+ {
+ for (const auto &e : _subgraphs)
+ {
+ if (std::dynamic_pointer_cast<Graph>(e.second) == nullptr)
+ return false;
+ }
+ return true;
+ }
+
+private:
+ std::unordered_map<SubgraphIndex, std::shared_ptr<IGraph>> _subgraphs;
+
+ // Custom operations support
+public:
+ void
+ bindKernelBuilder(const std::shared_ptr<onert::backend::custom::IKernelBuilder> &kernel_builder)
+ {
+ _kernel_builder = kernel_builder;
+ }
+
+ const std::shared_ptr<backend::custom::IKernelBuilder> &getKernelBuilder() const
+ {
+ return _kernel_builder;
+ }
private:
- std::unordered_map<SubgraphIndex, std::shared_ptr<Graph>> _subgraphs;
+ std::shared_ptr<backend::custom::IKernelBuilder> _kernel_builder;
};
} // namespace ir
diff --git a/runtime/onert/core/include/ir/NNPkg.h b/runtime/onert/core/include/ir/NNPkg.h
index b23745d55..5df58bde7 100644
--- a/runtime/onert/core/include/ir/NNPkg.h
+++ b/runtime/onert/core/include/ir/NNPkg.h
@@ -21,7 +21,6 @@
#include <unordered_set>
#include <vector>
-#include "ir/Graph.h"
#include "ir/Index.h"
#include "ir/Model.h"
@@ -233,7 +232,7 @@ public:
/**
* @brief Get model input info
*/
- OperandInfo &inputInfo(uint32_t index) const
+ const OperandInfo &inputInfo(uint32_t index) const
{
if (_models.size() == 1)
{
@@ -251,7 +250,7 @@ public:
/**
* @brief Get model output info
*/
- OperandInfo &outputInfo(uint32_t index) const
+ const OperandInfo &outputInfo(uint32_t index) const
{
if (_models.size() == 1)
{
@@ -266,6 +265,31 @@ public:
return graph->operands().at(operand_index).info();
}
+ void changeInputShape(uint32_t index, const ir::Shape &new_shape)
+ {
+ if (_models.size() == 1)
+ {
+ auto graph = primary_model()->primary_subgraph();
+ auto const operand_index = graph->getInputs().at(index);
+ graph->changeShape(operand_index, new_shape);
+ return;
+ }
+
+ auto const &desc = input(index);
+ auto graph = model(std::get<ModelIndex>(desc))->primary_subgraph();
+ auto const operand_index = graph->getInputs().at(std::get<IOIndex>(desc).value());
+ graph->changeShape(operand_index, new_shape);
+ }
+
+ /**
+ * @brief Replace model
+ *
+ * @param[in] model Model to be replaced
+ *
+ * TODO: Support multiple models
+ */
+ void replaceModel(std::shared_ptr<Model> model) { _models[ModelIndex{0}] = model; }
+
// TODO: Add iterate() or getter for edges
private:
diff --git a/runtime/onert/core/include/ir/OperandIndexSequence.h b/runtime/onert/core/include/ir/OperandIndexSequence.h
index 846c3f950..66d00761b 100644
--- a/runtime/onert/core/include/ir/OperandIndexSequence.h
+++ b/runtime/onert/core/include/ir/OperandIndexSequence.h
@@ -76,6 +76,7 @@ public:
}
public:
+ bool operator==(const OperandIndexSequence &other) const;
OperandIndexSequence operator+(const OperandIndexSequence &other) const;
friend std::ostream &operator<<(std::ostream &o, const OperandIndexSequence &operand_seq);
diff --git a/runtime/onert/core/include/ir/Operation.h b/runtime/onert/core/include/ir/Operation.h
index 89f7e340d..06ab29ecb 100644
--- a/runtime/onert/core/include/ir/Operation.h
+++ b/runtime/onert/core/include/ir/Operation.h
@@ -19,9 +19,8 @@
#include <memory>
-#include "ir/OpCode.h"
+#include "ir/IOperation.h"
#include "ir/Operand.h"
-#include "ir/OperandIndexSequence.h"
#include "ir/OperandConstraint.h"
namespace onert
@@ -29,9 +28,9 @@ namespace onert
namespace ir
{
-struct OperationVisitor;
-
-class Operation
+// NOTE Virtual inheritance is introduced because trainable operations inherit
+// `ITrainableOperation` and `Operation` which inherit `IOperation`.
+class Operation : virtual public IOperation
{
public:
// TODO Remove default parameter
@@ -49,16 +48,11 @@ public:
virtual ~Operation();
public:
- virtual void accept(OperationVisitor &v) const = 0;
- virtual std::string name() const { return std::string{toString(opcode())}; }
- virtual OpCode opcode() const = 0;
-
-public:
- void replaceInputs(const OperandIndex &from, const OperandIndex &to);
- void replaceOutputs(const OperandIndex &from, const OperandIndex &to);
+ void replaceInputs(const OperandIndex &from, const OperandIndex &to) override;
+ void replaceOutputs(const OperandIndex &from, const OperandIndex &to) override;
OperandIndexSequence &getInputs() { return _inputs; }
- const OperandIndexSequence &getInputs() const { return _inputs; }
- const OperandIndexSequence &getOutputs() const { return _outputs; }
+ const OperandIndexSequence &getInputs() const override { return _inputs; }
+ const OperandIndexSequence &getOutputs() const override { return _outputs; }
// It's for only input/output tensors but const data.
void setInputs(const OperandIndexSequence &indexes);
void setOutputs(const OperandIndexSequence &indexes);
diff --git a/runtime/onert/core/include/ir/Operations.Include.h b/runtime/onert/core/include/ir/Operations.Include.h
index 4602fafec..6352b8ed9 100644
--- a/runtime/onert/core/include/ir/Operations.Include.h
+++ b/runtime/onert/core/include/ir/Operations.Include.h
@@ -49,6 +49,7 @@
#include "ir/operation/L2Normalization.h"
#include "ir/operation/LocalResponseNormalization.h"
#include "ir/operation/LogSoftmax.h"
+#include "ir/operation/Loss.h"
#include "ir/operation/LSTM.h"
#include "ir/operation/MatrixBandPart.h"
#include "ir/operation/DetectionPostProcess.h"
diff --git a/runtime/onert/core/include/ir/Operations.h b/runtime/onert/core/include/ir/Operations.h
index 0b5fbf529..4102fcebe 100644
--- a/runtime/onert/core/include/ir/Operations.h
+++ b/runtime/onert/core/include/ir/Operations.h
@@ -18,7 +18,7 @@
#define __ONERT_IR_OPERATIONS_H__
#include "ir/Index.h"
-#include "ir/Operation.h"
+#include "ir/IOperation.h"
#include "util/ObjectManager.h"
namespace onert
@@ -26,7 +26,7 @@ namespace onert
namespace ir
{
-class Operations : public util::ObjectManager<OperationIndex, Operation>
+class Operations : public util::ObjectManager<OperationIndex, IOperation>
{
public:
Operations() = default;
diff --git a/runtime/onert/core/include/ir/Operations.lst b/runtime/onert/core/include/ir/Operations.lst
index f37d89505..1f91aecb2 100644
--- a/runtime/onert/core/include/ir/Operations.lst
+++ b/runtime/onert/core/include/ir/Operations.lst
@@ -88,3 +88,6 @@ OP(Transpose)
OP(TransposeConv)
OP(Unpack)
OP(While)
+
+// Training Only
+OP(Loss)
diff --git a/runtime/onert/core/include/ir/operation/BinaryArithmetic.h b/runtime/onert/core/include/ir/operation/BinaryArithmetic.h
index 110fff565..3dca80bbc 100644
--- a/runtime/onert/core/include/ir/operation/BinaryArithmetic.h
+++ b/runtime/onert/core/include/ir/operation/BinaryArithmetic.h
@@ -27,7 +27,7 @@ namespace ir
namespace operation
{
-class BinaryArithmetic final : public Operation
+class BinaryArithmetic : public Operation
{
public:
enum Input
diff --git a/runtime/onert/core/include/ir/operation/Loss.h b/runtime/onert/core/include/ir/operation/Loss.h
new file mode 100644
index 000000000..73f1aed59
--- /dev/null
+++ b/runtime/onert/core/include/ir/operation/Loss.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_IR_OPERATION_LOSS_H__
+#define __ONERT_IR_OPERATION_LOSS_H__
+
+#include "ir/Operation.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace operation
+{
+
+class Loss : public Operation
+{
+public:
+ enum Input
+ {
+ Y_PRED = 0,
+ Y_TRUE = 1
+ // TODO Add more inputs if necessary
+ };
+
+ // NOTE It is not yet determined how to get the information of the previous activation when
+ // generating kernels of Loss operation for each backend. If it is determined to get it
+ // from the object of this class, we have to consider whether to change this enum class.
+ enum class Type
+ {
+ MEAN_SQUARED_ERROR,
+ CATEGORICAL_CROSSENTROPY
+ };
+
+ struct Param
+ {
+ Type op_type;
+ // TODO Add more params if necessary
+ Param() : op_type(Type::MEAN_SQUARED_ERROR) {}
+ };
+
+public:
+ Loss(const OperandIndexSequence &inputs, const OperandIndexSequence &outputs, const Param &param);
+
+public:
+ void accept(OperationVisitor &v) const override;
+ std::string name() const override;
+ OpCode opcode() const final { return OpCode::Loss; }
+
+public:
+ const Param &param() const { return _param; }
+
+private:
+ Param _param;
+};
+
+} // namespace operation
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_OPERATION_LOSS_H__
diff --git a/runtime/onert/core/include/ir/train/ITrainableOperation.h b/runtime/onert/core/include/ir/train/ITrainableOperation.h
new file mode 100644
index 000000000..590bed45d
--- /dev/null
+++ b/runtime/onert/core/include/ir/train/ITrainableOperation.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_IR_TRAIN_ITRAINABLE_OPERATION_H__
+#define __ONERT_IR_TRAIN_ITRAINABLE_OPERATION_H__
+
+#include "ir/IOperation.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+
+struct TrainableOperationVisitor;
+
+// NOTE Virtual inheritance is introduced because trainable operations inherit
+// `ITrainableOperation` and `Operation` which inherit `IOperation`.
+class ITrainableOperation : virtual public IOperation
+{
+public:
+ virtual ~ITrainableOperation() = default;
+
+public:
+ virtual std::unique_ptr<ITrainableOperation> clone() const = 0;
+ virtual void accept(OperationVisitor &v) const override = 0;
+ virtual void accept(TrainableOperationVisitor &v) const = 0;
+ // TODO Add virtual methods related to training
+};
+
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_ITRAINABLE_OPERATION_H__
diff --git a/runtime/onert/core/include/ir/train/Operations.Include.h b/runtime/onert/core/include/ir/train/Operations.Include.h
new file mode 100644
index 000000000..56e752f94
--- /dev/null
+++ b/runtime/onert/core/include/ir/train/Operations.Include.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_IR_TRAIN_OPERATIONS_OPERATION_INCLUDE_H__
+#define __ONERT_IR_TRAIN_OPERATIONS_OPERATION_INCLUDE_H__
+
+#include "ir/train/operation/Conv2D.h"
+#include "ir/train/operation/ElementwiseActivation.h"
+#include "ir/train/operation/FullyConnected.h"
+#include "ir/train/operation/Loss.h"
+#include "ir/train/operation/Permute.h"
+#include "ir/train/operation/Pool2D.h"
+#include "ir/train/operation/Reshape.h"
+#include "ir/train/operation/Softmax.h"
+
+#endif // __ONERT_IR_TRAIN_OPERATIONS_OPERATION_INCLUDE_H__
diff --git a/runtime/onert/core/include/ir/train/Operations.lst b/runtime/onert/core/include/ir/train/Operations.lst
new file mode 100644
index 000000000..14dc38819
--- /dev/null
+++ b/runtime/onert/core/include/ir/train/Operations.lst
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OP
+#error Define OP before including this file
+#endif
+
+OP(Conv2D)
+OP(ElementwiseActivation)
+OP(FullyConnected)
+OP(Loss)
+OP(Permute)
+OP(Pool2D)
+OP(Reshape)
+OP(Softmax)
diff --git a/runtime/onert/core/include/ir/train/TrainableGraph.h b/runtime/onert/core/include/ir/train/TrainableGraph.h
new file mode 100644
index 000000000..90c49e212
--- /dev/null
+++ b/runtime/onert/core/include/ir/train/TrainableGraph.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_IR_TRAIN_TRAINABLE_GRAPH_H__
+#define __ONERT_IR_TRAIN_TRAINABLE_GRAPH_H__
+
+#include <functional>
+#include <unordered_map>
+
+#include "ir/Graph.h"
+#include "ir/train/ITrainableOperation.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+
+class TrainableGraph : public IGraph
+{
+public:
+ /**
+ * @brief Construct a new Trainable Graph object
+ *
+ * @param graph
+ */
+ explicit TrainableGraph();
+ explicit TrainableGraph(const TrainableGraph &tgraph);
+ explicit TrainableGraph(const Graph &graph);
+ ~TrainableGraph() = default;
+
+ // TrainableGraph Building
+public:
+ OperandIndex addOperand(const Shape &shape, const TypeInfo &type);
+ /**
+ * @brief Add an operand to the graph with the given index and object
+ *
+ * If the given index is available, it succeeds. And @c operand is moved which invalidates the
+ * caller's pointer. If the given index is already taken, it fails. And @c operand will not be
+ * moved so the caller's pointer will be still valid.
+ *
+ * @param[in] index Index to be added
+ * @param[in] operand Operand to be added
+ * @return OperandIndex @c index if successful, UNDEFINED otherwise
+ */
+ OperandIndex addOperand(OperandIndex index, std::unique_ptr<Operand> &&operand);
+ /**
+ * @brief Add a new trainable operation to the graph
+ *
+ * If the given @c operation has at least one invalid operand index, it fails. And @c operation
+ * will not be moved so the caller's pointer will be still valid.
+ *
+ * @param operation Operation to be added
+ * @return OperationIndex @c index if successful, UNDEFINED otherwise
+ */
+ OperationIndex addOperation(std::unique_ptr<ITrainableOperation> &&operation);
+ /**
+ * @brief Replace a trainable operation which the graph already has
+ *
+ * If the given @c index is available, it succeeds. And @c operation is moved which invalidates
+ * the caller's pointer. If the given @c operation has at least one invalid operand index, it
+ * fails. And @c operation will not be moved so the caller's pointer will be still valid.
+ *
+ * No information in the graph is changed except for replacing an operation.
+ *
+ * @param operation Operation to be added
+ * @return OperationIndex @c index if successful, UNDEFINED otherwise
+ */
+ OperationIndex replaceOperation(OperationIndex index,
+ std::unique_ptr<ITrainableOperation> &&operation);
+
+ /**
+ * @brief Add a derivative to the graph with the given index and object
+ *
+ * If the given index is available, it succeeds. And @c derivative is moved which invalidates the
+ * caller's pointer. If the given index is already taken, it fails. And @c derivative will not be
+ * moved so the caller's pointer will be still valid.
+ *
+ * @param[in] index Index to be added
+ * @param[in] derivative Derivative operand to be added
+ * @return OperandIndex @c index if successful, UNDEFINED otherwise
+ */
+ OperandIndex addDerivative(OperandIndex index, std::unique_ptr<Operand> &&derivative);
+
+public:
+ void changeShape(const OperandIndex &ind, const ir::Shape &new_shape) override;
+ void changeDerivativeShape(const OperandIndex &ind, const ir::Shape &new_shape);
+ void addInput(const OperandIndex &ind, const std::string &name = "");
+ void addOutput(const OperandIndex &ind, const std::string &name = "");
+ void addLoss(const OperandIndex &loss_ind, const IOIndex &pred_io_ind);
+ void verify() const;
+ void removeOperand(const OperandIndex &ind);
+ void setLayout(Layout layout);
+ void setInputs(OperandIndexSequence inputs,
+ std::unordered_map<std::string, IOIndex> name_to_input);
+ void setOutputs(OperandIndexSequence outputs,
+ std::unordered_map<std::string, IOIndex> name_to_output);
+
+ // Accessors
+public:
+ const OperandIndexSequence &getInputs() const override { return _graph.getInputs(); }
+ const OperandIndexSequence &getOutputs() const override { return _graph.getOutputs(); }
+ IOIndex getInputIndex(const std::string &name) const override;
+ IOIndex getOutputIndex(const std::string &name) const override;
+ const Operands &operands() const override { return _graph.operands(); }
+ Operands &operands() { return _graph.operands(); } // TODO Remove this non-const accessor
+ const Operations &operations() const override { return _graph.operations(); }
+ const Operands &derivatives() const { return _derivatives; }
+ OperandIndex getLossIndex(const IOIndex &pred_io_ind) const;
+ Layout layout() const { return _graph.layout(); }
+ const Graph &graph() const { return _graph; }
+
+public:
+ const ITrainableOperation &operation(OperationIndex index) const;
+
+public:
+ std::vector<ir::OperationIndex> topolSortOperations() const;
+ // TODO Support topological sort for backwarding
+
+private:
+ Graph _graph;
+ Operands _derivatives;
+
+ std::unordered_map<IOIndex, OperandIndex> _losses;
+};
+
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_TRAINABLE_GRAPH_H__
diff --git a/runtime/onert/core/include/ir/train/TrainableOperationVisitor.h b/runtime/onert/core/include/ir/train/TrainableOperationVisitor.h
new file mode 100644
index 000000000..fc58c351d
--- /dev/null
+++ b/runtime/onert/core/include/ir/train/TrainableOperationVisitor.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_IR_TRAIN_TRAINABLE_OPERATION_VISITOR_H__
+#define __ONERT_IR_TRAIN_TRAINABLE_OPERATION_VISITOR_H__
+
+#include "ir/train/Operations.Include.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+
+struct TrainableOperationVisitor
+{
+ virtual ~TrainableOperationVisitor() = default;
+
+#define OP(InternalName) \
+ virtual void visit(const operation::InternalName &) {}
+#include "ir/train/Operations.lst"
+#undef OP
+};
+
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_TRAINABLE_OPERATION_VISITOR_H__
diff --git a/runtime/onert/core/include/ir/train/operation/Conv2D.h b/runtime/onert/core/include/ir/train/operation/Conv2D.h
new file mode 100644
index 000000000..b8968926a
--- /dev/null
+++ b/runtime/onert/core/include/ir/train/operation/Conv2D.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_IR_TRAIN_OPERATION_CONV2D_H__
+#define __ONERT_IR_TRAIN_OPERATION_CONV2D_H__
+
+#include "ir/operation/Conv2D.h"
+#include "ir/train/ITrainableOperation.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+class Conv2D : public ir::operation::Conv2D, public ITrainableOperation
+{
+private:
+ using OperationType = ir::operation::Conv2D;
+
+public:
+ Conv2D(const OperationType &operation);
+
+public:
+ std::unique_ptr<ITrainableOperation> clone() const override;
+ void accept(OperationVisitor &v) const override;
+ void accept(TrainableOperationVisitor &v) const override;
+};
+
+} // namespace operation
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_OPERATION_CONV2D_H__
diff --git a/runtime/onert/core/include/ir/train/operation/ElementwiseActivation.h b/runtime/onert/core/include/ir/train/operation/ElementwiseActivation.h
new file mode 100644
index 000000000..97ab54d17
--- /dev/null
+++ b/runtime/onert/core/include/ir/train/operation/ElementwiseActivation.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_IR_TRAIN_OPERATION_ELEMENTWISE_ACTIVATION_H__
+#define __ONERT_IR_TRAIN_OPERATION_ELEMENTWISE_ACTIVATION_H__
+
+#include "ir/operation/ElementwiseActivation.h"
+#include "ir/train/ITrainableOperation.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+class ElementwiseActivation : public ir::operation::ElementwiseActivation,
+ public ITrainableOperation
+{
+private:
+ using OperationType = ir::operation::ElementwiseActivation;
+
+public:
+ ElementwiseActivation(const OperationType &operation);
+
+public:
+ std::unique_ptr<ITrainableOperation> clone() const override;
+ void accept(OperationVisitor &v) const override;
+ void accept(TrainableOperationVisitor &v) const override;
+};
+
+} // namespace operation
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_OPERATION_ELEMENTWISE_ACTIVATION_H__
diff --git a/runtime/onert/core/include/ir/train/operation/FullyConnected.h b/runtime/onert/core/include/ir/train/operation/FullyConnected.h
new file mode 100644
index 000000000..bede58d69
--- /dev/null
+++ b/runtime/onert/core/include/ir/train/operation/FullyConnected.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_IR_TRAIN_OPERATION_FULLYCONNECTED_H__
+#define __ONERT_IR_TRAIN_OPERATION_FULLYCONNECTED_H__
+
+#include "ir/operation/FullyConnected.h"
+#include "ir/train/ITrainableOperation.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+class FullyConnected : public ir::operation::FullyConnected, public ITrainableOperation
+{
+private:
+ using OperationType = ir::operation::FullyConnected;
+
+public:
+ FullyConnected(const OperationType &operation);
+
+public:
+ std::unique_ptr<ITrainableOperation> clone() const override;
+ void accept(OperationVisitor &v) const override;
+ void accept(TrainableOperationVisitor &v) const override;
+};
+
+} // namespace operation
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_OPERATION_FULLYCONNECTED_H__
diff --git a/runtime/onert/core/include/ir/train/operation/Loss.h b/runtime/onert/core/include/ir/train/operation/Loss.h
new file mode 100644
index 000000000..c7cc4213a
--- /dev/null
+++ b/runtime/onert/core/include/ir/train/operation/Loss.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_IR_TRAIN_OPERATION_LOSS_H__
+#define __ONERT_IR_TRAIN_OPERATION_LOSS_H__
+
+#include "ir/operation/Loss.h"
+#include "ir/train/ITrainableOperation.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+class Loss : public ir::operation::Loss, public ITrainableOperation
+{
+private:
+ using OperationType = ir::operation::Loss;
+
+public:
+ Loss(const OperationType &operation);
+
+public:
+ std::unique_ptr<ITrainableOperation> clone() const override;
+ void accept(OperationVisitor &v) const override;
+ void accept(TrainableOperationVisitor &v) const override;
+};
+
+} // namespace operation
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_OPERATION_LOSS_H__
diff --git a/runtime/onert/core/include/ir/train/operation/Permute.h b/runtime/onert/core/include/ir/train/operation/Permute.h
new file mode 100644
index 000000000..e652b136d
--- /dev/null
+++ b/runtime/onert/core/include/ir/train/operation/Permute.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_IR_TRAIN_OPERATION_PERMUTE_H__
+#define __ONERT_IR_TRAIN_OPERATION_PERMUTE_H__
+
+#include "ir/operation/Permute.h"
+#include "ir/train/ITrainableOperation.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+class Permute : public ir::operation::Permute, public ITrainableOperation
+{
+private:
+ using OperationType = ir::operation::Permute;
+
+public:
+ Permute(const OperationType &operation);
+
+public:
+ std::unique_ptr<ITrainableOperation> clone() const override;
+ void accept(OperationVisitor &v) const override;
+ void accept(TrainableOperationVisitor &v) const override;
+};
+
+} // namespace operation
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_OPERATION_PERMUTE_H__
diff --git a/runtime/onert/core/include/ir/train/operation/Pool2D.h b/runtime/onert/core/include/ir/train/operation/Pool2D.h
new file mode 100644
index 000000000..024997074
--- /dev/null
+++ b/runtime/onert/core/include/ir/train/operation/Pool2D.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_IR_TRAIN_OPERATION_POOL2D_H__
+#define __ONERT_IR_TRAIN_OPERATION_POOL2D_H__
+
+#include "ir/operation/Pool2D.h"
+#include "ir/train/ITrainableOperation.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+class Pool2D : public ir::operation::Pool2D, public ITrainableOperation
+{
+private:
+ using OperationType = ir::operation::Pool2D;
+
+public:
+ Pool2D(const OperationType &operation);
+
+public:
+ std::unique_ptr<ITrainableOperation> clone() const override;
+ void accept(OperationVisitor &v) const override;
+ void accept(TrainableOperationVisitor &v) const override;
+};
+
+} // namespace operation
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_OPERATION_POOL2D_H__
diff --git a/runtime/onert/core/include/ir/train/operation/Reshape.h b/runtime/onert/core/include/ir/train/operation/Reshape.h
new file mode 100644
index 000000000..1efd62cfe
--- /dev/null
+++ b/runtime/onert/core/include/ir/train/operation/Reshape.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_IR_TRAIN_OPERATION_RESHAPE_H__
+#define __ONERT_IR_TRAIN_OPERATION_RESHAPE_H__
+
+#include "ir/operation/Reshape.h"
+#include "ir/train/ITrainableOperation.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+class Reshape : public ir::operation::Reshape, public ITrainableOperation
+{
+private:
+ using OperationType = ir::operation::Reshape;
+
+public:
+ Reshape(const OperationType &operation);
+
+public:
+ std::unique_ptr<ITrainableOperation> clone() const override;
+ void accept(OperationVisitor &v) const override;
+ void accept(TrainableOperationVisitor &v) const override;
+};
+
+} // namespace operation
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_OPERATION_RESHAPE_H__
diff --git a/runtime/onert/core/include/ir/train/operation/Softmax.h b/runtime/onert/core/include/ir/train/operation/Softmax.h
new file mode 100644
index 000000000..b12e6abc1
--- /dev/null
+++ b/runtime/onert/core/include/ir/train/operation/Softmax.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_IR_TRAIN_OPERATION_SOFTMAX_H__
+#define __ONERT_IR_TRAIN_OPERATION_SOFTMAX_H__
+
+#include "ir/operation/Softmax.h"
+#include "ir/train/ITrainableOperation.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+class Softmax : public ir::operation::Softmax, public ITrainableOperation
+{
+private:
+ using OperationType = ir::operation::Softmax;
+
+public:
+ Softmax(const OperationType &operation);
+
+public:
+ std::unique_ptr<ITrainableOperation> clone() const override;
+ void accept(OperationVisitor &v) const override;
+ void accept(TrainableOperationVisitor &v) const override;
+};
+
+} // namespace operation
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_OPERATION_SOFTMAX_H__
diff --git a/runtime/onert/core/include/ir/train/operation/UntrainableOperation.h b/runtime/onert/core/include/ir/train/operation/UntrainableOperation.h
new file mode 100644
index 000000000..7cda0ec0c
--- /dev/null
+++ b/runtime/onert/core/include/ir/train/operation/UntrainableOperation.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_IR_TRAIN_OPERATION_UNTRAINABLE_OPERATION_H__
+#define __ONERT_IR_TRAIN_OPERATION_UNTRAINABLE_OPERATION_H__
+
+#include "ir/train/ITrainableOperation.h"
+
+#include "ir/OperationVisitor.h"
+#include "ir/train/TrainableOperationVisitor.h"
+
+#include <type_traits>
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+// `UntrainableOperation` wraps operations that are not yet supported for training.
+// This class can be removed if all operations are supported for training.
+template <typename OperationType,
+ typename = std::enable_if_t<std::is_base_of<Operation, OperationType>::value>>
+class UntrainableOperation : public OperationType, public ITrainableOperation
+{
+public:
+ UntrainableOperation(const OperationType &operation) : OperationType{operation} {}
+ virtual ~UntrainableOperation() = default;
+
+public:
+ std::unique_ptr<ITrainableOperation> clone() const override
+ {
+ return std::make_unique<UntrainableOperation<OperationType>>(*this);
+ }
+ void accept(OperationVisitor &v) const override { v.visit(*this); }
+ void accept(TrainableOperationVisitor &) const override
+ {
+ throw std::runtime_error(OperationType::name() + "operation is not trainable yet");
+ }
+};
+
+} // namespace operation
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_OPERATION_UNTRAINABLE_OPERATION_H__
diff --git a/runtime/onert/core/include/odc/IQuantizer.h b/runtime/onert/core/include/odc/IQuantizer.h
new file mode 100644
index 000000000..d698d9ef0
--- /dev/null
+++ b/runtime/onert/core/include/odc/IQuantizer.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_ODC_IQUANTIZER_H__
+#define __ONERT_ODC_IQUANTIZER_H__
+
+namespace onert
+{
+namespace odc
+{
+
+class IQuantizer
+{
+public:
+ virtual ~IQuantizer() = default;
+
+ virtual int quantize(const char *in, const char *out, bool is_q16) = 0;
+};
+
+} // namespace odc
+} // namespace onert
+
+#endif // __ONERT_ODC_IQUANTIZER_H__
diff --git a/runtime/onert/core/include/odc/QuantizeManager.h b/runtime/onert/core/include/odc/QuantizeManager.h
new file mode 100644
index 000000000..a749c0ee1
--- /dev/null
+++ b/runtime/onert/core/include/odc/QuantizeManager.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_ODC_QUANTIZE_MANAGER_H__
+#define __ONERT_ODC_QUANTIZE_MANAGER_H__
+
+#include "IQuantizer.h"
+
+#include <functional>
+#include <string>
+
+namespace onert
+{
+namespace odc
+{
+
+class Quantize;
+
+class QuantizeManager
+{
+public:
+ // Non-copyable
+ QuantizeManager() = delete;
+ QuantizeManager(const std::string &model_path) : _model_path(model_path) {}
+ QuantizeManager(QuantizeManager const &) = delete;
+ QuantizeManager &operator=(QuantizeManager const &) = delete;
+
+public:
+ /**
+ * @brief Set model path to export quantized model
+ *
+ * @param model_path Model path to export quantized model
+ */
+ void exportModelPath(const std::string &model_path) { _export_model_path = model_path; }
+
+ /**
+ * @brief Get model path to export quantized model
+ *
+ * @return Model path to export quantized model
+ */
+ std::string &exportModelPath() { return _export_model_path; }
+
+ /**
+ * @brief Set quantize type
+ *
+ * @param is_q16 true if q16, false if q8
+ *
+ * @todo Support more general quantize type
+ */
+ void quantizeType(bool is_q16) { _is_q16 = is_q16; }
+
+ /**
+ * @brief Quantize model
+ *
+ * @return true if success, otherwise false
+ */
+ bool quantize();
+
+private:
+ std::string _model_path = "";
+ std::string _export_model_path = "";
+ bool _is_q16 = false;
+};
+
+} // namespace odc
+} // namespace onert
+
+#endif // __ONERT_ODC_QUANTIZE_MANAGER_H__
diff --git a/runtime/onert/core/include/util/Config.lst b/runtime/onert/core/include/util/Config.lst
index b9bad1b59..d3e37ce8f 100644
--- a/runtime/onert/core/include/util/Config.lst
+++ b/runtime/onert/core/include/util/Config.lst
@@ -31,6 +31,7 @@ CONFIG(NCNN_LAYOUT , std::string , "NCHW")
CONFIG(PROFILING_MODE , bool , "0")
CONFIG(USE_SCHEDULER , bool , "0")
CONFIG(TRACE_FILEPATH , std::string , "")
+CONFIG(MINMAX_FILEPATH , std::string , "")
CONFIG(FP16_ENABLE , bool , "0")
CONFIG(RUY_THREADS , int , "-1")
CONFIG(XNNPACK_THREADS , int , "-1")
diff --git a/runtime/onert/core/include/util/MinMaxMap.h b/runtime/onert/core/include/util/MinMaxMap.h
new file mode 100644
index 000000000..2245f84b0
--- /dev/null
+++ b/runtime/onert/core/include/util/MinMaxMap.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_UTIL_MINMAX_MAP_H_
+#define __ONERT_UTIL_MINMAX_MAP_H_
+
+#include <unordered_map>
+#include <utility>
+
+namespace onert
+{
+namespace util
+{
+
+template <typename N, typename Hash = std::hash<N>> class MinMaxMap
+{
+ struct MinMaxPair
+ {
+ float data[2]; // [0] = min, [1] = max
+ };
+
+public:
+ void append(N node, float min, float max) { _minmax_map[node] = {min, max}; }
+ auto begin() const { return _minmax_map.begin(); }
+ auto end() const { return _minmax_map.end(); }
+
+private:
+ std::unordered_map<N, MinMaxPair, Hash> _minmax_map;
+};
+
+} // namespace util
+} // namespace onert
+
+#endif // __ONERT_UTIL_MINMAX_MAP_H_
diff --git a/runtime/onert/core/include/util/Set.h b/runtime/onert/core/include/util/Set.h
index ee4062d25..73d43d4f0 100644
--- a/runtime/onert/core/include/util/Set.h
+++ b/runtime/onert/core/include/util/Set.h
@@ -53,6 +53,16 @@ public:
public:
/**
+ * @brief copy assignment operator
+ */
+ Set<Element> &operator=(const Set<Element> &) = default;
+ /**
+ * @brief move assignment operator
+ */
+ Set<Element> &operator=(Set<Element> &&) = default;
+
+public:
+ /**
* @brief Add a given element to the set
*
* @param e Element added
@@ -104,7 +114,7 @@ public:
Set<Element> operator|(const Set<Element> &other) const // Union
{
auto ret = *this;
- for (auto e : other)
+ for (auto &&e : other)
{
ret.add(e);
}
@@ -118,7 +128,7 @@ public:
Set<Element> operator&(const Set<Element> &other) const // Intersect
{
Set<Element> ret;
- for (auto e : other)
+ for (auto &&e : other)
{
if (contains(e))
{
@@ -135,7 +145,7 @@ public:
Set<Element> operator-(const Set<Element> &other) const // Minus
{
auto ret = *this;
- for (auto e : other)
+ for (auto &&e : other)
{
ret.remove(e);
}
diff --git a/runtime/onert/core/include/util/Utils.h b/runtime/onert/core/include/util/Utils.h
index 505f5a9b3..6b6bc2400 100644
--- a/runtime/onert/core/include/util/Utils.h
+++ b/runtime/onert/core/include/util/Utils.h
@@ -27,73 +27,56 @@
#define UNUSED_RELEASE(a) (void)(a)
-template <size_t from, size_t to, typename Enable = void> struct ForEachDimension
+template <size_t rest> struct ForEachDimension
{
template <typename L>
static void unroll(const onert::ir::Shape &shape, onert::ir::Coordinates &coords,
L lambda_function)
{
- static_assert(from < to, "from must not be less than to");
- assert(static_cast<int>(to) <= shape.rank());
- const auto &d = shape.dim(from);
+ if (static_cast<int>(rest) > shape.rank())
+ {
+ ForEachDimension<rest - 1>::unroll(shape, coords, lambda_function);
+ return;
+ }
+
+ const auto axis = shape.rank() - rest;
+ const auto &d = shape.dim(axis);
for (auto v = 0; v < d; v++)
{
- coords.set(from, v);
- ForEachDimension<from + 1, to>::unroll(shape, coords, lambda_function);
+ coords.set(axis, v);
+ ForEachDimension<rest - 1>::unroll(shape, coords, lambda_function);
}
}
};
-template <size_t from, size_t to>
-struct ForEachDimension<from, to, typename std::enable_if<from == to>::type>
+template <> struct ForEachDimension<0>
{
template <typename L>
static void unroll(const onert::ir::Shape &shape, onert::ir::Coordinates &coords,
L lambda_function)
{
UNUSED_RELEASE(shape);
- assert(static_cast<int>(to) <= shape.rank());
lambda_function(coords);
}
};
template <typename L> inline void ShapeLoop(const onert::ir::Shape &shape, L lambda_function)
{
- assert(shape.rank() > 0);
- for (auto i = 0; i < shape.rank(); ++i)
+ int32_t rank = shape.rank();
+ assert(rank > 0);
+ for (int32_t i = 0; i < rank; ++i)
{
assert(shape.dim(i) > 0);
}
onert::ir::Coordinates coords;
- switch (shape.rank())
+ if (rank == 0)
{
- case 0:
- coords.set(0, 0);
- ForEachDimension<0, 0>::unroll(shape, coords, lambda_function);
- break;
- case 1:
- ForEachDimension<0, 1>::unroll(shape, coords, lambda_function);
- break;
- case 2:
- ForEachDimension<0, 2>::unroll(shape, coords, lambda_function);
- break;
- case 3:
- ForEachDimension<0, 3>::unroll(shape, coords, lambda_function);
- break;
- case 4:
- ForEachDimension<0, 4>::unroll(shape, coords, lambda_function);
- break;
- case 5:
- ForEachDimension<0, 5>::unroll(shape, coords, lambda_function);
- break;
- case 6:
- ForEachDimension<0, 6>::unroll(shape, coords, lambda_function);
- break;
- default:
- assert(false && "ShapeLoop, 1 <= Shape'rank <= 6");
- break;
+ coords.set(0, 0);
}
+ // TODO Change 6 to onert::ir::Shape::kMaxRank if onert::ir::Shape::kMaxRank is modified as a
+ // constant expression
+ ForEachDimension<6>::unroll(shape, coords, lambda_function);
}
#endif // __ONERT_UTIL_UTILS_H__
diff --git a/runtime/onert/core/src/backend/BackendContext.cc b/runtime/onert/core/src/backend/BackendContext.cc
index b9aab7994..7b36f106d 100644
--- a/runtime/onert/core/src/backend/BackendContext.cc
+++ b/runtime/onert/core/src/backend/BackendContext.cc
@@ -16,8 +16,6 @@
#include "backend/BackendContext.h"
-#include "ir/Operation.h"
-
namespace onert
{
namespace backend
diff --git a/runtime/onert/core/src/backend/basic/StaticTensorManager.cc b/runtime/onert/core/src/backend/basic/StaticTensorManager.cc
index b03eb607c..71cde4cde 100644
--- a/runtime/onert/core/src/backend/basic/StaticTensorManager.cc
+++ b/runtime/onert/core/src/backend/basic/StaticTensorManager.cc
@@ -35,6 +35,15 @@ StaticTensorManager::StaticTensorManager(const std::shared_ptr<TensorRegistry> &
// DO NOTHING
}
+StaticTensorManager::StaticTensorManager(const std::shared_ptr<TensorRegistry> &reg,
+ const std::string planner_id,
+ DynamicTensorManager *dynamic_tensor_manager)
+ : _nonconst_mgr{new MemoryManager(planner_id)}, _tensors{reg}, _dynamic_tensor_manager{
+ dynamic_tensor_manager}
+{
+ // DO NOTHING
+}
+
void StaticTensorManager::allocateNonconsts(void)
{
_nonconst_mgr->allocate();
diff --git a/runtime/onert/core/src/backend/basic/Tensor.cc b/runtime/onert/core/src/backend/basic/Tensor.cc
index c2bbc5a66..de1cff4f4 100644
--- a/runtime/onert/core/src/backend/basic/Tensor.cc
+++ b/runtime/onert/core/src/backend/basic/Tensor.cc
@@ -51,6 +51,7 @@ bool Tensor::applyShape(const ir::Shape &new_shape)
auto allocTensorMem = [&]() {
auto capacity = total_size();
+ assert(_dynamic_mem_mgr);
auto alloc = _dynamic_mem_mgr->allocate(this, capacity);
setBuffer(alloc);
};
@@ -68,6 +69,7 @@ bool Tensor::applyShape(const ir::Shape &new_shape)
auto new_size = new_shape.num_elements() * ir::sizeOfDataType(data_type());
if (previous_size != new_size)
{
+ assert(_dynamic_mem_mgr);
_dynamic_mem_mgr->deallocate(this);
setShape(new_shape);
diff --git a/runtime/onert/core/src/backend/basic/TensorBuilder.cc b/runtime/onert/core/src/backend/basic/TensorBuilder.cc
index a10cc2bf9..f9d83875d 100644
--- a/runtime/onert/core/src/backend/basic/TensorBuilder.cc
+++ b/runtime/onert/core/src/backend/basic/TensorBuilder.cc
@@ -34,6 +34,14 @@ TensorBuilder::TensorBuilder(const std::shared_ptr<TensorRegistry> &tensor_reg)
/* empty */
}
+TensorBuilder::TensorBuilder(const std::shared_ptr<TensorRegistry> &tensor_reg,
+ const std::string planner_id)
+ : _tensor_reg{tensor_reg}, _dynamic_tensor_mgr{new DynamicTensorManager(_tensor_reg)},
+ _static_tensor_mgr{new StaticTensorManager(_tensor_reg, planner_id, _dynamic_tensor_mgr.get())}
+{
+ /* empty */
+}
+
void TensorBuilder::registerTensorInfo(const ir::OperandIndex &ind, const ir::OperandInfo &info,
ir::Layout layout)
{
diff --git a/runtime/onert/core/src/backend/basic/train/TrainableTensor.cc b/runtime/onert/core/src/backend/basic/train/TrainableTensor.cc
new file mode 100644
index 000000000..d09604224
--- /dev/null
+++ b/runtime/onert/core/src/backend/basic/train/TrainableTensor.cc
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <backend/basic/train/TrainableTensor.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace basic
+{
+namespace train
+{
+
+std::vector<ITensor *> TrainableTensor::optVars()
+{
+ std::vector<ITensor *> ret;
+ for (auto &&e : _opt_vars)
+ {
+ ret.emplace_back(e.get());
+ }
+ return ret;
+}
+
+void TrainableTensor::fillBuffer(const std::shared_ptr<ir::Data> &data)
+{
+ auto *buffer = _tensor.buffer();
+ assert(buffer);
+ assert(total_size() == data->size());
+ std::memcpy(buffer, data->base(), data->size());
+}
+
+} // namespace train
+} // namespace basic
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/core/src/backend/builtin/Backend.h b/runtime/onert/core/src/backend/builtin/Backend.h
index 3791f3ffa..c05494a6a 100644
--- a/runtime/onert/core/src/backend/builtin/Backend.h
+++ b/runtime/onert/core/src/backend/builtin/Backend.h
@@ -22,8 +22,16 @@
#include "KernelGenerator.h"
#include "TensorBuilder.h"
#include "Tensor.h"
+#ifdef ONERT_TRAIN
+#include "train/BackendContext.h"
+#include "train/KernelGenerator.h"
+#include "train/TensorRegistry.h"
+#endif // ONERT_TRAIN
#include <backend/Backend.h>
+#ifdef ONERT_TRAIN
+#include <backend/train/ITrainableBackend.h>
+#endif // ONERT_TRAIN
#include <memory>
@@ -35,6 +43,10 @@ namespace builtin
{
class Backend : public ::onert::backend::Backend
+#ifdef ONERT_TRAIN
+ ,
+ public backend::train::ITrainableBackend
+#endif // ONERT_TRAIN
{
public:
Backend() : _config{std::make_shared<Config>()} {}
@@ -70,6 +82,22 @@ public:
return context;
}
+#ifdef ONERT_TRAIN
+ std::unique_ptr<backend::train::TrainableBackendContext>
+ newContext(backend::train::TrainableContextData &&tdata) const override
+ {
+ const auto &tgraph = *tdata.tgraph;
+ auto tr = std::make_shared<train::TensorRegistry>();
+ // TODO Create TensorBuilder if necessary
+ auto tdata_ptr = std::make_unique<backend::train::TrainableContextData>(std::move(tdata));
+ auto context = std::make_unique<train::BackendContext>(this, std::move(tdata_ptr), tr);
+
+ context->kernel_gen =
+ std::make_shared<train::KernelGenerator>(tgraph, tr, context->external_context());
+ return context;
+ }
+#endif // ONERT_TRAIN
+
private:
std::shared_ptr<IConfig> _config;
};
diff --git a/runtime/onert/core/src/backend/builtin/BackendContext.cc b/runtime/onert/core/src/backend/builtin/BackendContext.cc
index c1a2ed537..573617e28 100644
--- a/runtime/onert/core/src/backend/builtin/BackendContext.cc
+++ b/runtime/onert/core/src/backend/builtin/BackendContext.cc
@@ -32,7 +32,7 @@ FunctionMap BackendContext::genKernels()
{
FunctionMap ret;
- for (auto op_ind : _data.op_order)
+ for (auto &&op_ind : _data.op_order)
{
auto fn_seq = kernel_gen->generate(op_ind);
ret.emplace_back(op_ind, std::move(fn_seq));
diff --git a/runtime/onert/core/src/backend/builtin/Config.cc b/runtime/onert/core/src/backend/builtin/Config.cc
index f792c0c36..e5f6d4c21 100644
--- a/runtime/onert/core/src/backend/builtin/Config.cc
+++ b/runtime/onert/core/src/backend/builtin/Config.cc
@@ -27,7 +27,7 @@ std::string Config::ID = "builtin";
bool Config::initialize() { return true; }
-ir::Layout Config::supportLayout(const ir::Operation &, ir::Layout frontend_layout)
+ir::Layout Config::supportLayout(const ir::IOperation &, ir::Layout frontend_layout)
{
return frontend_layout;
}
diff --git a/runtime/onert/core/src/backend/builtin/Config.h b/runtime/onert/core/src/backend/builtin/Config.h
index 5226eba69..196b299d3 100644
--- a/runtime/onert/core/src/backend/builtin/Config.h
+++ b/runtime/onert/core/src/backend/builtin/Config.h
@@ -34,7 +34,7 @@ public:
static std::string ID;
std::string id() override { return ID; }
bool initialize() override;
- ir::Layout supportLayout(const ir::Operation &node, ir::Layout frontend_layout) override;
+ ir::Layout supportLayout(const ir::IOperation &node, ir::Layout frontend_layout) override;
bool supportPermutation() override { return false; }
bool supportDynamicTensor() override
{
diff --git a/runtime/onert/core/src/backend/builtin/KernelGenerator.cc b/runtime/onert/core/src/backend/builtin/KernelGenerator.cc
index 4533703a6..00c200a92 100644
--- a/runtime/onert/core/src/backend/builtin/KernelGenerator.cc
+++ b/runtime/onert/core/src/backend/builtin/KernelGenerator.cc
@@ -71,14 +71,14 @@ void KernelGenerator::visit(const ir::operation::If &node)
const auto else_subg_index = node.param().else_subg_index;
std::vector<backend::IPortableTensor *> input_tensors;
- for (const auto input_index : node.getInputs())
+ for (const auto &input_index : node.getInputs())
{
auto input_tensor = getPortableTensor(input_index);
input_tensors.emplace_back(input_tensor);
}
std::vector<backend::IPortableTensor *> output_tensors;
- for (const auto output_index : node.getOutputs())
+ for (const auto &output_index : node.getOutputs())
{
auto output_tensor = getPortableTensor(output_index);
output_tensors.emplace_back(output_tensor);
@@ -117,14 +117,14 @@ void KernelGenerator::visit(const ir::operation::While &node)
// This op does not support input as a constant, because builtin backend does not have
// TensorBuilder
std::vector<backend::IPortableTensor *> input_tensors;
- for (const auto input_index : node.getInputs())
+ for (const auto &input_index : node.getInputs())
{
auto input_tensor = getPortableTensor(input_index);
input_tensors.emplace_back(input_tensor);
}
std::vector<backend::IPortableTensor *> output_tensors;
- for (const auto output_index : node.getOutputs())
+ for (const auto &output_index : node.getOutputs())
{
auto output_tensor = getPortableTensor(output_index);
output_tensors.emplace_back(output_tensor);
diff --git a/runtime/onert/core/src/backend/builtin/kernel/WhileLayer.cc b/runtime/onert/core/src/backend/builtin/kernel/WhileLayer.cc
index c0ca4046c..8b00db468 100644
--- a/runtime/onert/core/src/backend/builtin/kernel/WhileLayer.cc
+++ b/runtime/onert/core/src/backend/builtin/kernel/WhileLayer.cc
@@ -96,7 +96,7 @@ void WhileLayer::run()
// Need some temp tensors to hold the body subgraph output
std::vector<std::unique_ptr<Tensor>> temp_outputs_o;
std::vector<IPortableTensor *> temp_outputs;
- for (auto io_tensor : body_exec->getOutputTensors())
+ for (auto &&io_tensor : body_exec->getOutputTensors())
{
auto tensor = std::make_unique<Tensor>(io_tensor->orig_info(), io_tensor->orig_layout(),
_dyn_memory_manager);
@@ -139,7 +139,7 @@ void WhileLayer::run()
// Clean-up the temp tensors
_dyn_memory_manager->deallocate(cond_output_tensor.get());
- for (auto tensor : temp_outputs)
+ for (auto &&tensor : temp_outputs)
{
_dyn_memory_manager->deallocate(tensor);
}
diff --git a/runtime/onert/core/src/backend/builtin/train/BackendContext.cc b/runtime/onert/core/src/backend/builtin/train/BackendContext.cc
new file mode 100644
index 000000000..fa9131f4d
--- /dev/null
+++ b/runtime/onert/core/src/backend/builtin/train/BackendContext.cc
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "BackendContext.h"
+
+#include "backend/basic/train/TrainableBackendContextHelpers.h"
+#include "exec/FunctionSequence.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace builtin
+{
+namespace train
+{
+
+backend::ITensorRegistry *BackendContext::genTensors()
+{
+ // For now, there is no need to generate tensors for forwarding.
+ // builtin train backend handles 3 operators: `Permute`, `IF`, `WHILE`.
+ // `Permute`: Tensor generation is not required.
+ // `IF`, `WHILE`: Not supported yet
+ return tensor_registry().get();
+}
+
+backend::train::ITensorRegistry *BackendContext::genTrainingTensors()
+{
+ // For now, there is no need to generate tensors for backwarding.
+ return tensor_registry().get();
+}
+
+backend::train::FunctionMap BackendContext::genKernels()
+{
+ backend::train::FunctionMap ret;
+
+ for (auto &&op_ind : _tdata->op_order)
+ {
+ auto tn_seq = kernel_gen->generate(op_ind);
+ ret.emplace_back(op_ind, std::move(tn_seq));
+ }
+
+ trainable_graph()->operands().iterate(
+ [&](const ir::OperandIndex &ind, const ir::Operand &operand) {
+ if (!external_operands().contains(ind) && operand.isConstant())
+ {
+ throw std::runtime_error(
+ "BackendContext: builtin backend does not support updatable weights yet");
+ }
+ });
+
+ // TODO Enable prepare()
+ // for (auto &&it : ret)
+ // {
+ // auto &fn_seq = it.second;
+ // fn_seq->iterate([&](exec::IFunction &ifunc) { ifunc.prepare(); });
+ // }
+
+ return ret;
+}
+
+} // namespace train
+} // namespace builtin
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/core/src/backend/builtin/train/BackendContext.h b/runtime/onert/core/src/backend/builtin/train/BackendContext.h
new file mode 100644
index 000000000..6f8ce4cae
--- /dev/null
+++ b/runtime/onert/core/src/backend/builtin/train/BackendContext.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_BUILTIN_TRAIN_BACKEND_CONTEXT_H__
+#define __ONERT_BACKEND_BUILTIN_TRAIN_BACKEND_CONTEXT_H__
+
+#include <backend/train/TrainableBackendContext.h>
+
+#include "KernelGenerator.h"
+#include "../ExternalContext.h"
+#include "../TensorBuilder.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace builtin
+{
+namespace train
+{
+
+class BackendContext : public backend::train::TrainableBackendContext
+{
+public:
+ BackendContext(const backend::train::ITrainableBackend *backend,
+ std::unique_ptr<backend::train::TrainableContextData> &&data,
+ std::shared_ptr<backend::train::ITensorRegistry> tensor_registry = nullptr,
+ std::shared_ptr<TensorBuilder> tensor_builder = nullptr,
+ std::shared_ptr<KernelGenerator> kernel_gen = nullptr)
+ : backend::train::TrainableBackendContext(backend, std::move(data), tensor_registry),
+ kernel_gen{kernel_gen},
+ _external_context(new ExternalContext), _tensor_builder{tensor_builder}
+ {
+ }
+
+ backend::ITensorRegistry *genTensors() override;
+ backend::train::ITensorRegistry *genTrainingTensors() override;
+
+public:
+ backend::train::FunctionMap genKernels() override;
+
+ std::shared_ptr<ExternalContext> external_context() { return _external_context; }
+
+public:
+ // TODO Make it private
+ std::shared_ptr<KernelGenerator> kernel_gen;
+
+private:
+ // NOTE ruy context has a thread pool, and when multiple ruy contexts are created,
+ // the thread pool is also created in duplicate
+ // TODO Create one ruy context for session
+ std::shared_ptr<ExternalContext> _external_context;
+
+private:
+ std::shared_ptr<TensorBuilder> _tensor_builder;
+};
+
+} // namespace train
+} // namespace builtin
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_BUILTIN_TRAIN_BACKEND_CONTEXT_H__
diff --git a/runtime/onert/core/src/backend/builtin/train/KernelGenerator.cc b/runtime/onert/core/src/backend/builtin/train/KernelGenerator.cc
new file mode 100644
index 000000000..6f2c0a3b9
--- /dev/null
+++ b/runtime/onert/core/src/backend/builtin/train/KernelGenerator.cc
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "KernelGenerator.h"
+
+#include "kernel/PermuteLayer.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace builtin
+{
+namespace train
+{
+
+KernelGenerator::KernelGenerator(const ir::train::TrainableGraph &tgraph,
+ const std::shared_ptr<TensorRegistry> &tensor_reg,
+ const std::shared_ptr<ExternalContext> &external_context)
+ : KernelGeneratorBase{tgraph}, _tensor_reg{tensor_reg}, _external_context(external_context)
+{
+}
+
+std::unique_ptr<exec::train::TrainableFnSequence> KernelGenerator::generate(ir::OperationIndex ind)
+{
+ auto ret = std::make_unique<exec::train::TrainableFnSequence>();
+ const auto &op = _tgraph.operation(ind);
+ op.accept(*this);
+ // _return_fn must have been generated
+ if (_return_fn == nullptr)
+ {
+ throw std::runtime_error(op.name() + " op does not supported trainable kernel yet");
+ }
+
+ ret->_functions.emplace_back(std::move(_return_fn));
+
+ return ret;
+}
+
+void KernelGenerator::visit(const ir::train::operation::Permute &node)
+{
+ const auto output_index{node.getOutputs().at(0)};
+ const auto input_index{node.getInputs().at(0)};
+
+ // Add PermuteLayer
+ std::vector<ITensor *> output_tensors{getTensor(output_index)};
+ std::vector<ITensor *> input_tensors{getTensor(input_index)};
+
+ std::vector<ITensor *> output_deriv_tensors;
+ std::vector<ITensor *> input_deriv_tensors;
+
+ auto input_deriv_tensor = getDerivativeTensor(input_index);
+ auto output_deriv_tensor = getDerivativeTensor(output_index);
+ output_deriv_tensors.emplace_back(output_deriv_tensor);
+ input_deriv_tensors.emplace_back(input_deriv_tensor);
+
+ // NOTE IOTensors of graph outputs for passing data to users must be ignored in training
+ // because the buffers of those IOTensors are unnecessary and nullptr
+ bool ignore_forward_in_training = _whole_graph_outputs.contains(output_index);
+ auto fn = std::make_unique<kernel::PermuteLayer>(input_tensors, output_tensors,
+ input_deriv_tensors, output_deriv_tensors,
+ ignore_forward_in_training, _external_context);
+
+ _return_fn = std::move(fn);
+}
+
+backend::ITensor *KernelGenerator::getTensor(const ir::OperandIndex &index)
+{
+ // Get Tensor from all tensor registries (for Permute op)
+ auto ret = _tensor_registries.getITensor(index);
+ assert(ret != nullptr);
+ return ret;
+}
+
+backend::ITensor *KernelGenerator::getDerivativeTensor(const ir::OperandIndex &index)
+{
+ // Get derivative Tensor from all tensor registries (for Permute op)
+ auto ret = _tensor_registries.getDerivativeITensor(index);
+ return ret;
+}
+
+} // namespace train
+} // namespace builtin
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/core/src/backend/builtin/train/KernelGenerator.h b/runtime/onert/core/src/backend/builtin/train/KernelGenerator.h
new file mode 100644
index 000000000..d8781c0d0
--- /dev/null
+++ b/runtime/onert/core/src/backend/builtin/train/KernelGenerator.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_BUTIN_TRAIN_KERNEL_GENERATOR_H__
+#define __ONERT_BACKEND_BUTIN_TRAIN_KERNEL_GENERATOR_H__
+
+#include "../ExternalContext.h"
+#include "../train/TensorRegistry.h"
+#include "../../../compiler/train/TensorRegistries.h"
+
+#include <backend/train/KernelGeneratorBase.h>
+#include <exec/train/TrainableFnSequence.h>
+#include <ir/train/TrainableGraph.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace builtin
+{
+namespace train
+{
+
+class KernelGenerator : public backend::train::KernelGeneratorBase
+{
+public:
+ KernelGenerator(const ir::train::TrainableGraph &tgraph,
+ const std::shared_ptr<TensorRegistry> &tensor_reg,
+ const std::shared_ptr<ExternalContext> &external_context);
+
+ std::unique_ptr<exec::train::TrainableFnSequence> generate(ir::OperationIndex ind) override;
+
+ void setTensorRegistries(const compiler::train::TensorRegistries &tensor_registries)
+ {
+ _tensor_registries = tensor_registries;
+ }
+
+ void setWholeGraphOutputs(const ir::OperandIndexSequence &outputs)
+ {
+ _whole_graph_outputs = outputs;
+ }
+
+private:
+ void visit(const ir::train::operation::Permute &) override;
+
+private:
+ backend::ITensor *getTensor(const ir::OperandIndex &index);
+ backend::ITensor *getDerivativeTensor(const ir::OperandIndex &index);
+
+private:
+ std::shared_ptr<TensorRegistry> _tensor_reg;
+ compiler::train::TensorRegistries _tensor_registries;
+ const std::shared_ptr<ExternalContext> _external_context;
+ ir::OperandIndexSequence _whole_graph_outputs;
+};
+
+} // namespace train
+} // namespace builtin
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_BUTIN_TRAIN_KERNEL_GENERATOR_H__
diff --git a/runtime/onert/core/src/backend/builtin/train/Tensor.h b/runtime/onert/core/src/backend/builtin/train/Tensor.h
new file mode 100644
index 000000000..611407bd2
--- /dev/null
+++ b/runtime/onert/core/src/backend/builtin/train/Tensor.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_BUILTIN_TRAIN_TRAINABLE_TENSOR_H__
+#define __ONERT_BACKEND_BUILTIN_TRAIN_TRAINABLE_TENSOR_H__
+
+#include <backend/basic/train/TrainableTensor.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace builtin
+{
+namespace train
+{
+
+using TrainableTensor = basic::train::TrainableTensor;
+using DerivativeTensor = basic::Tensor;
+using GradientTensor = basic::Tensor;
+
+} // namespace train
+} // namespace builtin
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_BUILTIN_TRAIN_TRAINABLE_TENSOR_H__
diff --git a/runtime/onert/core/src/backend/builtin/train/TensorRegistry.h b/runtime/onert/core/src/backend/builtin/train/TensorRegistry.h
new file mode 100644
index 000000000..c48e5fe93
--- /dev/null
+++ b/runtime/onert/core/src/backend/builtin/train/TensorRegistry.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_BUILTIN_TRAIN_TENSOR_REGISTRY_H__
+#define __ONERT_BACKEND_BUILTIN_TRAIN_TENSOR_REGISTRY_H__
+
+#include <backend/train/ITensorRegistry.h>
+
+#include "../IOTensor.h"
+#include "../Tensor.h"
+#include "Tensor.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace builtin
+{
+namespace train
+{
+
+using BaseTensorRegistry =
+ backend::train::PortableTensorRegistryTemplate<Tensor, TrainableTensor, DerivativeTensor,
+ GradientTensor>;
+
+class TensorRegistry : public backend::train::ITensorRegistry
+{
+public:
+ TensorRegistry() : _base_reg{new BaseTensorRegistry} {}
+
+ ITensor *getITensor(const ir::OperandIndex &index) override
+ {
+ auto base_tensor = _base_reg->getITensor(index);
+ if (base_tensor)
+ return base_tensor;
+ return getNativeIOTensor(index);
+ }
+
+ ITensor *getNativeITensor(const ir::OperandIndex &index) override
+ {
+ auto base_tensor = _base_reg->getNativeITensor(index);
+ if (base_tensor)
+ return base_tensor;
+ return getNativeIOTensor(index);
+ }
+
+ IPortableTensor *getPortableTensor(const ir::OperandIndex &index)
+ {
+ auto base_tensor = _base_reg->getPortableTensor(index);
+ if (base_tensor)
+ return base_tensor;
+ return getNativeIOTensor(index);
+ }
+
+ IOTensor *getNativeIOTensor(const ir::OperandIndex &index)
+ {
+ auto tensor = _native_io_tensors.find(index);
+ if (tensor != _native_io_tensors.end())
+ return tensor->second.get();
+ return nullptr;
+ }
+
+ ITensor *getDerivativeITensor(const ir::OperandIndex &index) override
+ {
+ return _base_reg->getDerivativeTensor(index);
+ }
+
+ ITensor *getGradientITensor(const ir::OperandIndex &index) override
+ {
+ return _base_reg->getGradientTensor(index);
+ }
+
+ DerivativeTensor *getDerivativeTensor(const ir::OperandIndex &index)
+ {
+ return _base_reg->getDerivativeTensor(index);
+ }
+
+ bool setMigrantTensor(const ir::OperandIndex &index, IPortableTensor *tensor) override
+ {
+ assert(tensor);
+ assert(!getITensor(index)); // For the index, tensor is not registered yet
+ _base_reg->setMigrantTensor(index, tensor);
+ return true;
+ }
+
+ void setDerivativeTensor(const ir::OperandIndex &index, std::unique_ptr<DerivativeTensor> tensor)
+ {
+ _base_reg->setDerivativeTensor(index, std::move(tensor));
+ }
+
+ void setGradientTensor(const ir::OperandIndex &index, std::unique_ptr<GradientTensor> tensor)
+ {
+ _base_reg->setGradientTensor(index, std::move(tensor));
+ }
+
+ void setNativeIOTensor(ir::OperandIndex index, std::unique_ptr<IOTensor> &&tensor)
+ {
+ assert(tensor);
+ assert(!getITensor(index)); // For the index, tensor is not registered yet
+ _native_io_tensors[index] = std::move(tensor);
+ }
+
+ const ir::OperandIndexMap<std::unique_ptr<IOTensor>> &native_io_tensors()
+ {
+ return _native_io_tensors;
+ }
+ std::shared_ptr<BaseTensorRegistry> base_reg() { return _base_reg; }
+
+private:
+ std::shared_ptr<BaseTensorRegistry> _base_reg;
+ ir::OperandIndexMap<std::unique_ptr<IOTensor>> _native_io_tensors;
+};
+
+} // namespace train
+} // namespace builtin
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_BUILTIN_TRAIN_TENSOR_REGISTRY_H__
diff --git a/runtime/onert/core/src/backend/builtin/train/kernel/PermuteLayer.cc b/runtime/onert/core/src/backend/builtin/train/kernel/PermuteLayer.cc
new file mode 100644
index 000000000..929092dde
--- /dev/null
+++ b/runtime/onert/core/src/backend/builtin/train/kernel/PermuteLayer.cc
@@ -0,0 +1,85 @@
+
+
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PermuteLayer.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace builtin
+{
+namespace train
+{
+namespace kernel
+{
+
+PermuteLayer::PermuteLayer(const std::vector<ITensor *> &src_tensors,
+ const std::vector<ITensor *> &dst_tensors,
+ const std::vector<ITensor *> &input_deriv_tensors,
+ const std::vector<ITensor *> &output_deriv_tensors,
+ bool ignore_forward_in_training,
+ const std::shared_ptr<ExternalContext> &external_context)
+ : builtin::kernel::PermuteLayer{src_tensors, dst_tensors, external_context},
+ _input_deriv_tensors{input_deriv_tensors}, _output_deriv_tensors{output_deriv_tensors},
+ _ignore_forward_in_training{ignore_forward_in_training}
+{
+ assert(input_deriv_tensors.size() == output_deriv_tensors.size());
+ assert(src_tensors.size() == dst_tensors.size());
+}
+
+void PermuteLayer::optimize()
+{
+ builtin::kernel::PermuteLayer::optimize();
+
+ // TODO Calculate offsets of derivative tensors if necessary
+}
+
+void PermuteLayer::forward(bool training)
+{
+ if (training && _ignore_forward_in_training)
+ return;
+
+ builtin::kernel::PermuteLayer::run();
+}
+
+void PermuteLayer::backward()
+{
+ for (uint32_t i = 0; i < _output_deriv_tensors.size(); ++i)
+ {
+ auto src_deriv = _output_deriv_tensors.at(i);
+ auto dst_deriv = _input_deriv_tensors.at(i);
+
+ // NOTE The derivative tensors corresponding to inputs/outputs of model are nullptr
+ // because permuting those tensors is meaningless
+ if (src_deriv && dst_deriv)
+ {
+ const auto rank = src_deriv->getShape().rank();
+ auto output_offsets = _dst_tensors_offsets.at(i);
+ auto input_offsets = _src_tensors_offsets.at(i);
+
+ exec::IPermuteFunction::permute(src_deriv, dst_deriv, rank, output_offsets, input_offsets);
+ }
+ }
+}
+
+} // namespace kernel
+} // namespace train
+} // namespace builtin
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/core/src/backend/builtin/train/kernel/PermuteLayer.h b/runtime/onert/core/src/backend/builtin/train/kernel/PermuteLayer.h
new file mode 100644
index 000000000..de8063a21
--- /dev/null
+++ b/runtime/onert/core/src/backend/builtin/train/kernel/PermuteLayer.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_BACKEND_BUILTIN_TRAIN_KERNEL_PERMUTELAYER_H__
+#define __ONERT_BACKEND_BUILTIN_TRAIN_KERNEL_PERMUTELAYER_H__
+
+#include "../../kernel/PermuteLayer.h"
+
+#include "exec/train/ITrainableFunction.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace builtin
+{
+namespace train
+{
+namespace kernel
+{
+
+class PermuteLayer : public builtin::kernel::PermuteLayer, public exec::train::ITrainableFunction
+{
+public:
+ PermuteLayer(const std::vector<ITensor *> &src_tensors, const std::vector<ITensor *> &dst_tensors,
+ const std::vector<ITensor *> &input_deriv_tensors,
+ const std::vector<ITensor *> &output_deriv_tensors, bool ignore_forward_in_training,
+ const std::shared_ptr<ExternalContext> &external_context);
+
+ void optimize() override;
+
+ void forward(bool training) override;
+ void backward() override;
+
+private:
+ std::vector<ITensor *> _input_deriv_tensors;
+ std::vector<ITensor *> _output_deriv_tensors;
+ bool _ignore_forward_in_training;
+};
+
+} // namespace kernel
+} // namespace train
+} // namespace builtin
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_BUILTIN_TRAIN_KERNEL_PERMUTELAYER_H__
diff --git a/runtime/onert/core/src/compiler/Compiler.cc b/runtime/onert/core/src/compiler/Compiler.cc
index 45124556b..ba621bb4f 100644
--- a/runtime/onert/core/src/compiler/Compiler.cc
+++ b/runtime/onert/core/src/compiler/Compiler.cc
@@ -16,6 +16,7 @@
#include "compiler/Compiler.h"
+#include "CompilerHelpers.h"
#include "ExecutorFactory.h"
#include "ShapeValidator.h"
#include "pass/ConstantOutputPass.h"
@@ -30,6 +31,7 @@
#include "compiler/StaticShapeInferer.h"
#include <misc/string_helpers.h>
+#include <misc/polymorphic_downcast.h>
namespace onert
{
@@ -69,10 +71,25 @@ std::shared_ptr<CompilerArtifact> Compiler::compile(void)
throw std::runtime_error("Profiling mode works only with 'Dataflow' executor");
}
+ if (!_options->minmax_filepath.empty())
+ {
+ if (_options->executor != "Linear")
+ throw std::runtime_error("Recording minmax works only with Linear executor");
+ }
+
+ if (!_model->hasOnly<ir::Graph>())
+ {
+ throw std::runtime_error("Compiler can only compile models for inference.");
+ }
+
_options->forceInternalOptions();
_options->verboseOptions();
- _model->iterate([&](const ir::SubgraphIndex &, ir::Graph &subg) {
+ auto custom_kernel_builder = _model->getKernelBuilder();
+
+ _model->iterate([&](const ir::SubgraphIndex &, ir::IGraph &graph) {
+ auto &subg = nnfw::misc::polymorphic_downcast<ir::Graph &>(graph);
+
// Mandatory passes
pass::PassRunner{}
.append(std::make_unique<pass::ConstantOutputPass>(subg))
@@ -96,7 +113,9 @@ std::shared_ptr<CompilerArtifact> Compiler::compile(void)
// Lower: Assign backend
std::unordered_map<ir::SubgraphIndex, std::unique_ptr<compiler::LoweredGraph>> lowered_subgs;
{
- _model->iterate([&](const ir::SubgraphIndex &subg_index, ir::Graph &subg) {
+ _model->iterate([&](const ir::SubgraphIndex &subg_index, ir::IGraph &graph) {
+ auto &subg = nnfw::misc::polymorphic_downcast<ir::Graph &>(graph);
+
// Lower: Assign backend
lowered_subgs[subg_index] = std::make_unique<compiler::LoweredGraph>(subg, *_options);
// Set tracing_ctx for copied graph
@@ -119,7 +138,7 @@ std::shared_ptr<CompilerArtifact> Compiler::compile(void)
// Run the StaticShapeInfer of primary subg. All child StaticShapeInferers are called
// recursively
std::unordered_map<ir::SubgraphIndex, std::unique_ptr<StaticShapeInferer>> inferers =
- StaticShapeInferer::createStaticShapeInferers(lowered_subgs);
+ createStaticShapeInferers(lowered_subgs);
const auto primary_subg_idx = ir::SubgraphIndex{0};
inferers.at(primary_subg_idx)->infer();
@@ -158,10 +177,15 @@ std::shared_ptr<CompilerArtifact> Compiler::compile(void)
ir::OperationDumper dumper("Executor generation of Subgraph " +
std::to_string(subg_index.value()));
lowered_subg->graph().operations().iterate(
- [&](const ir::OperationIndex &, const ir::Operation &op) { op.accept(dumper); });
-
- auto executor = std::unique_ptr<exec::IExecutor>{ExecutorFactory::get().create(
- std::move(lowered_subg), tracing_ctx.get(), *_options, executors, model_index)};
+ [&](const ir::OperationIndex &, const ir::IOperation &op) { op.accept(dumper); });
+
+ ExecutorFactoryArgs args;
+ args.tracing_ctx = tracing_ctx.get();
+ args.options = _options;
+ args.model_index = model_index;
+ args.custom_kernel_builder = custom_kernel_builder;
+ auto executor = std::unique_ptr<exec::IExecutor>{
+ ExecutorFactory::get().create(std::move(lowered_subg), executors, args)};
executor->setIndexedRanks(indexed_ranks);
executors->emplace(model_index, subg_index, std::move(executor));
}
diff --git a/runtime/onert/core/src/compiler/CompilerFactory.cc b/runtime/onert/core/src/compiler/CompilerFactory.cc
index d8d4bb277..aeb0876c4 100644
--- a/runtime/onert/core/src/compiler/CompilerFactory.cc
+++ b/runtime/onert/core/src/compiler/CompilerFactory.cc
@@ -17,6 +17,9 @@
#include "compiler/CompilerFactory.h"
#include "MultiModelCompiler.h"
+#ifdef ONERT_TRAIN
+#include "train/TrainingCompiler.h"
+#endif // ONERT_TRAIN
#include "compiler/Compiler.h"
@@ -33,8 +36,18 @@ CompilerFactory &CompilerFactory::get()
std::unique_ptr<ICompiler>
CompilerFactory::create(const std::shared_ptr<ir::NNPkg> &nnpkg,
- std::vector<std::unique_ptr<CompilerOptions>> &copts)
+ std::vector<std::unique_ptr<CompilerOptions>> &copts,
+ const compiler::train::TrainingInfo *training_info)
{
+#ifdef ONERT_TRAIN
+ // Returing compiler for training
+ if (training_info)
+ return std::make_unique<train::TrainingCompiler>(nnpkg, copts, *training_info);
+#else // ONERT_TRAIN
+ (void)training_info;
+#endif // ONERT_TRAIN
+
+ // Returing compiler for inference
if (nnpkg->model_count() == 1)
return std::make_unique<Compiler>(nnpkg, copts);
diff --git a/runtime/onert/core/src/compiler/CompilerHelpers.h b/runtime/onert/core/src/compiler/CompilerHelpers.h
new file mode 100644
index 000000000..798334b3b
--- /dev/null
+++ b/runtime/onert/core/src/compiler/CompilerHelpers.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_COMPILER_COMPILER_HELPERS_H__
+#define __ONERT_COMPILER_COMPILER_HELPERS_H__
+
+#include <compiler/ILoweredGraph.h>
+#include <compiler/StaticShapeInferer.h>
+#include <ir/Index.h>
+
+#include <memory>
+#include <unordered_map>
+
+namespace onert
+{
+namespace compiler
+{
+
+/**
+ * @brief Create a shape inferer map for a lowered model
+ * @param[in] lowered_subgs lowered model map
+ * @return Shape inferer map
+ */
+template <typename LoweredGraphType,
+ typename = std::enable_if_t<std::is_base_of<ILoweredGraph, LoweredGraphType>::value>>
+static std::unordered_map<ir::SubgraphIndex, std::unique_ptr<StaticShapeInferer>>
+createStaticShapeInferers(
+ const std::unordered_map<ir::SubgraphIndex, std::unique_ptr<LoweredGraphType>> &lowered_subgs)
+{
+ std::unordered_map<ir::SubgraphIndex, ILoweredGraph *> lsubgs;
+ for (auto &&e : lowered_subgs)
+ lsubgs[e.first] = e.second.get();
+ return StaticShapeInferer::createStaticShapeInferers(lsubgs);
+}
+
+} // namespace compiler
+} // namespace onert
+
+#endif // __ONERT_COMPILER_COMPILER_HELPERS_H__
diff --git a/runtime/onert/core/src/compiler/CompilerOptions.cc b/runtime/onert/core/src/compiler/CompilerOptions.cc
index b5fd392e0..830d9dd00 100644
--- a/runtime/onert/core/src/compiler/CompilerOptions.cc
+++ b/runtime/onert/core/src/compiler/CompilerOptions.cc
@@ -75,6 +75,7 @@ std::unique_ptr<CompilerOptions> CompilerOptions::fromGlobalConfig()
{
auto o = std::make_unique<CompilerOptions>();
o->backend_list = nnfw::misc::split(util::getConfigString(util::config::BACKENDS), ';');
+ o->minmax_filepath = util::getConfigString(util::config::MINMAX_FILEPATH);
o->trace_filepath = util::getConfigString(util::config::TRACE_FILEPATH);
o->graph_dump_level = util::getConfigInt(util::config::GRAPH_DOT_DUMP);
o->executor = util::getConfigString(util::config::EXECUTOR);
diff --git a/runtime/onert/core/src/compiler/ExecutorFactory.cc b/runtime/onert/core/src/compiler/ExecutorFactory.cc
index b09d6b021..6a08524cc 100644
--- a/runtime/onert/core/src/compiler/ExecutorFactory.cc
+++ b/runtime/onert/core/src/compiler/ExecutorFactory.cc
@@ -25,6 +25,9 @@
#include "../exec/ExecTime.h"
#include "../exec/ExecutionObservers.h"
#include "../exec/LinearExecutor.h"
+#ifdef MINMAX_H5DUMPER
+#include "../exec/MinMaxRecorder.h"
+#endif
#include "../exec/ParallelExecutor.h"
#include "../ir/OperationCloner.h"
@@ -36,6 +39,14 @@
#include <functional>
#include <memory>
+#ifdef ONERT_TRAIN
+#include "../backend/builtin/train/BackendContext.h"
+#include "../exec/train/TrainableExecutor.h"
+
+#include <backend/train/TrainableBackendContext.h>
+#include <backend/train/ITrainableBackend.h>
+#endif // ONERT_TRAIN
+
namespace onert
{
namespace
@@ -74,7 +85,7 @@ public:
void run() override
{
- for (auto tensor : _dealloc_list)
+ for (auto &&tensor : _dealloc_list)
{
if (!tensor->is_dynamic())
continue;
@@ -86,7 +97,8 @@ private:
DeallocList _dealloc_list;
};
-void initializeSubgraphIOTensors(compiler::LoweredGraph &lowered_graph,
+// TODO Unify initializeSubgraphIOTensors
+void initializeSubgraphIOTensors(compiler::ILoweredGraph &lowered_graph,
const backend::BackendContexts &backend_contexts,
const ir::OperandIndexSequence &indices)
{
@@ -104,7 +116,38 @@ void initializeSubgraphIOTensors(compiler::LoweredGraph &lowered_graph,
}
assert(builtin_tensor_reg);
- for (auto ind : indices)
+ for (auto &&ind : indices)
+ {
+ const auto &operand = lowered_graph.graph().operands().at(ind);
+ auto tensor = std::make_unique<backend::builtin::IOTensor>(
+ operand.info(),
+ ir::Layout::NHWC /* FIXME find operation for this operand and use frontend_layout */
+ );
+
+ // Add tensor to builtin TensorRegistry.
+ builtin_tensor_reg->setNativeIOTensor(ind, std::move(tensor));
+ }
+}
+
+#ifdef ONERT_TRAIN
+void initializeSubgraphIOTensors(compiler::ILoweredGraph &lowered_graph,
+ const backend::train::TrainableBackendContexts &backend_contexts,
+ const ir::OperandIndexSequence &indices)
+{
+ std::shared_ptr<backend::builtin::train::TensorRegistry> builtin_tensor_reg;
+ for (const auto &e : backend_contexts)
+ {
+ auto backend = e.first;
+ auto &context = e.second;
+ if (backend->config()->id() == backend::builtin::Config::ID)
+ {
+ builtin_tensor_reg = std::dynamic_pointer_cast<backend::builtin::train::TensorRegistry>(
+ context->tensor_registry());
+ }
+ }
+ assert(builtin_tensor_reg);
+
+ for (auto &&ind : indices)
{
const auto &operand = lowered_graph.graph().operands().at(ind);
auto tensor = std::make_unique<backend::builtin::IOTensor>(
@@ -116,8 +159,11 @@ void initializeSubgraphIOTensors(compiler::LoweredGraph &lowered_graph,
builtin_tensor_reg->setNativeIOTensor(ind, std::move(tensor));
}
}
+#endif // ONERT_TRAIN
-backend::BackendContexts createBackendContexts(compiler::LoweredGraph &lgraph, bool linear_executor)
+backend::BackendContexts
+createBackendContexts(compiler::ILoweredGraph &lgraph, bool linear_executor,
+ std::shared_ptr<backend::custom::IKernelBuilder> custom_kernel_builder)
{
backend::BackendContexts contexts;
auto &backend_manager = compiler::BackendManager::get();
@@ -125,7 +171,7 @@ backend::BackendContexts createBackendContexts(compiler::LoweredGraph &lgraph, b
std::unordered_map<const backend::Backend *, backend::ContextData> context_data_map;
// Generate partial graphs for each backend
- for (auto backend : backend_manager.getAll())
+ for (auto &&backend : backend_manager.getAll())
{
auto &data = context_data_map[backend];
auto graph = std::make_unique<ir::Graph>();
@@ -157,7 +203,7 @@ backend::BackendContexts createBackendContexts(compiler::LoweredGraph &lgraph, b
});
// Separate operations into partial graphs
whole_graph.operations().iterate(
- [&](const ir::OperationIndex &op_ind, const ir::Operation &operation) {
+ [&](const ir::OperationIndex &op_ind, const ir::IOperation &operation) {
auto &op_li = lgraph.lower_info().operation;
auto backend = op_li.at(op_ind).backend();
auto &partial_graph = *context_data_map[backend].graph;
@@ -168,7 +214,7 @@ backend::BackendContexts createBackendContexts(compiler::LoweredGraph &lgraph, b
// Add missing operands (externals)
auto io_list = (operation.getInputs() + operation.getOutputs()) | ir::Remove::DUPLICATED |
ir::Remove::UNDEFINED;
- for (auto operand_ind : io_list)
+ for (auto &&operand_ind : io_list)
{
if (partial_graph.operands().exist(operand_ind))
continue;
@@ -217,12 +263,33 @@ backend::BackendContexts createBackendContexts(compiler::LoweredGraph &lgraph, b
std::copy_if(whole_op_order.begin(), whole_op_order.end(), std::back_inserter(data.op_order),
[&](const auto &ind) { return data.graph->operations().exist(ind); });
data.is_linear_executor = linear_executor;
- data.custom_kernel_builder = lgraph.graph().getKernelBuilder();
+ data.custom_kernel_builder = custom_kernel_builder;
contexts.emplace(backend, backend->newContext(std::move(data)));
}
return contexts;
}
+template <typename Context>
+std::deque<std::pair<const backend::Backend *, Context *>> orderBackendContext(
+ const std::unordered_map<const backend::Backend *, std::unique_ptr<Context>> &tbackend_contexts)
+{
+ std::deque<std::pair<const backend::Backend *, Context *>> ordered_contexts;
+
+ for (auto &&pair : tbackend_contexts)
+ {
+ // NOTE builtin backend must be processed lastly.
+ // This is because of Permute layer's specialty which is the only operation that could have
+ // different ITensor objects for the input and the output. And it requires all other backends'
+ // tensors are ready to use.
+ if (pair.first->config()->id() == "builtin")
+ ordered_contexts.emplace_back(pair.first, pair.second.get());
+ else
+ ordered_contexts.emplace_front(pair.first, pair.second.get());
+ }
+
+ return ordered_contexts;
+}
+
} // namespace
} // namespace onert
@@ -240,34 +307,30 @@ ExecutorFactory &ExecutorFactory::get()
ExecutorFactory::ExecutorFactory()
{
_map["Linear"] = createLinearExecutor;
- _map["Dataflow"] =
- std::bind(createDataflowExecutor, std::placeholders::_1, std::placeholders::_2,
- std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, false);
- _map["Parallel"] =
- std::bind(createDataflowExecutor, std::placeholders::_1, std::placeholders::_2,
- std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, true);
+ _map["Dataflow"] = std::bind(createDataflowExecutor, std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3, false);
+ _map["Parallel"] = std::bind(createDataflowExecutor, std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3, true);
}
exec::IExecutor *ExecutorFactory::create(std::unique_ptr<compiler::LoweredGraph> lowered_graph,
- const util::TracingCtx *tracing_ctx,
- const compiler::CompilerOptions &options,
const std::shared_ptr<exec::IExecutors> &executors,
- const ir::ModelIndex &index)
+ const ExecutorFactoryArgs &args)
{
- return _map.at(options.executor)(std::move(lowered_graph), tracing_ctx, options, executors,
- index);
+ assert(args.options != nullptr);
+ return _map.at(args.options->executor)(std::move(lowered_graph), executors, args);
}
-void ExecutorFactory::prepareMigrantTensors(compiler::LoweredGraph &lowered_graph,
+void ExecutorFactory::prepareMigrantTensors(compiler::ILoweredGraph &lowered_graph,
const backend::BackendContexts &backend_contexts)
{
TensorRegistries tensor_regs{backend_contexts, true};
lowered_graph.graph().operations().iterate(
- [&](const ir::OperationIndex &op_ind, const ir::Operation &op) {
+ [&](const ir::OperationIndex &op_ind, const ir::IOperation &op) {
auto lower_info = lowered_graph.lower_info().operation.getRawPtr(op_ind);
auto &backend_ctx = backend_contexts.at(lower_info->backend());
- for (auto ind :
+ for (auto &&ind :
(op.getInputs() + op.getOutputs()) | ir::Remove::DUPLICATED | ir::Remove::UNDEFINED)
{
// If an Operation's input/output tensor does not have an own tensor object,
@@ -307,7 +370,6 @@ std::deque<std::pair<const backend::Backend *, backend::BackendContext *>>
ExecutorFactory::orderBackendContext(const backend::BackendContexts &backend_contexts)
{
std::deque<std::pair<const backend::Backend *, backend::BackendContext *>> ordered_contexts;
-
for (auto &&pair : backend_contexts)
{
// NOTE builtin backend must be processed lastly.
@@ -319,19 +381,22 @@ ExecutorFactory::orderBackendContext(const backend::BackendContexts &backend_con
else
ordered_contexts.emplace_front(pair.first, pair.second.get());
}
-
return ordered_contexts;
}
-exec::IExecutor *ExecutorFactory::createLinearExecutor(
- std::unique_ptr<compiler::LoweredGraph> lowered_graph, const util::TracingCtx *tracing_ctx,
- const compiler::CompilerOptions &options, const std::shared_ptr<exec::IExecutors> &executors,
- const ir::ModelIndex &index)
+exec::IExecutor *
+ExecutorFactory::createLinearExecutor(std::unique_ptr<compiler::LoweredGraph> lowered_graph,
+ const std::shared_ptr<exec::IExecutors> &executors,
+ const ExecutorFactoryArgs &args)
{
+ const auto options = args.options;
+ const auto &model_index = args.model_index;
+ const auto tracing_ctx = args.tracing_ctx;
+ auto custom_kernel_builder = args.custom_kernel_builder;
auto &graph = lowered_graph->graph();
backend::BackendContexts backend_contexts =
- createBackendContexts(*lowered_graph, options.executor == "Linear");
+ createBackendContexts(*lowered_graph, options->executor == "Linear", custom_kernel_builder);
TensorRegistries tensor_regs{backend_contexts, true};
@@ -352,7 +417,7 @@ exec::IExecutor *ExecutorFactory::createLinearExecutor(
prepareMigrantTensors(*lowered_graph, backend_contexts);
// Give some runtime objects to builtin KernelGenerator
- prepareBuiltinBackend(tensor_regs, executors, backend_contexts, index);
+ prepareBuiltinBackend(tensor_regs, executors, backend_contexts, model_index);
ExecutionBuilder builder;
@@ -382,7 +447,7 @@ exec::IExecutor *ExecutorFactory::createLinearExecutor(
uses_map[ind]++;
}
- for (const auto op_ind : order)
+ for (const auto &op_ind : order)
{
const auto &op = graph.operations().at(op_ind);
auto op_inputs = op.getInputs() | ir::Remove::DUPLICATED | ir::Remove::UNDEFINED;
@@ -422,7 +487,7 @@ exec::IExecutor *ExecutorFactory::createLinearExecutor(
auto &fn_seq = pair.second;
auto &op = lowered_graph->graph().operations().at(op_ind);
auto lower_info = lowered_graph->lower_info().operation.getRawPtr(op_ind);
- if (options.he_profiling_mode)
+ if (options->he_profiling_mode)
fn_seq->wrap<SyncFunction>(lower_info->backend()->config());
if (!dealloc_list_map[op_ind].empty())
fn_seq->append(std::make_unique<DeallocFunction>(dealloc_list_map[op_ind]));
@@ -439,23 +504,33 @@ exec::IExecutor *ExecutorFactory::createLinearExecutor(
order,
tracing_ctx};
- if (!options.trace_filepath.empty())
+ if (!options->trace_filepath.empty())
{
std::unique_ptr<exec::IExecutionObserver> ctp =
- std::make_unique<exec::TracingObserver>(options.trace_filepath, exec->graph(), tracing_ctx);
+ std::make_unique<exec::TracingObserver>(options->trace_filepath, exec->graph(), tracing_ctx);
exec->addObserver(std::move(ctp));
}
+#ifdef MINMAX_H5DUMPER
+ if (!options->minmax_filepath.empty())
+ exec->addObserver(std::make_unique<exec::MinMaxRecorder>(
+ options->minmax_filepath, exec->graph(), exec->getBackendContexts()));
+#endif
return exec;
}
-exec::IExecutor *ExecutorFactory::createDataflowExecutor(
- std::unique_ptr<compiler::LoweredGraph> lowered_graph, const util::TracingCtx *tracing_ctx,
- const compiler::CompilerOptions &options, const std::shared_ptr<exec::IExecutors> &executors,
- const ir::ModelIndex &index, bool parallel)
+exec::IExecutor *
+ExecutorFactory::createDataflowExecutor(std::unique_ptr<compiler::LoweredGraph> lowered_graph,
+ const std::shared_ptr<exec::IExecutors> &executors,
+ const ExecutorFactoryArgs &args, bool parallel)
{
+ const auto options = args.options;
+ const auto &model_index = args.model_index;
+ const auto tracing_ctx = args.tracing_ctx;
+ auto custom_kernel_builder = args.custom_kernel_builder;
+
backend::BackendContexts backend_contexts =
- createBackendContexts(*lowered_graph, options.executor == "Linear");
+ createBackendContexts(*lowered_graph, options->executor == "Linear", custom_kernel_builder);
TensorRegistries tensor_regs{backend_contexts, true};
@@ -472,7 +547,7 @@ exec::IExecutor *ExecutorFactory::createDataflowExecutor(
prepareMigrantTensors(*lowered_graph, backend_contexts);
// Give some runtime objects to builtin KernelGenerator
- prepareBuiltinBackend(tensor_regs, executors, backend_contexts, index);
+ prepareBuiltinBackend(tensor_regs, executors, backend_contexts, model_index);
ExecutionBuilder builder;
@@ -489,7 +564,7 @@ exec::IExecutor *ExecutorFactory::createDataflowExecutor(
auto &fn_seq = pair.second;
auto &op = lowered_graph->graph().operations().at(op_ind);
auto lower_info = lowered_graph->lower_info().operation.getRawPtr(op_ind);
- if (options.he_profiling_mode)
+ if (options->he_profiling_mode)
fn_seq->wrap<SyncFunction>(lower_info->backend()->config());
builder.append(op_ind, {op_ind, &op, lower_info, std::move(fn_seq)});
}
@@ -508,7 +583,7 @@ exec::IExecutor *ExecutorFactory::createDataflowExecutor(
auto dataflow_exec =
new exec::DataflowExecutor{std::move(lowered_graph), std::move(backend_contexts), tensor_regs,
std::move(code_map), tracing_ctx};
- if (options.he_profiling_mode)
+ if (options->he_profiling_mode)
{
std::vector<const backend::Backend *> backends;
for (const auto &pair : backend_contexts)
@@ -523,15 +598,304 @@ exec::IExecutor *ExecutorFactory::createDataflowExecutor(
exec = dataflow_exec;
}
- if (!options.trace_filepath.empty())
+ if (!options->trace_filepath.empty())
+ {
+ std::unique_ptr<exec::IExecutionObserver> ctp =
+ std::make_unique<exec::TracingObserver>(options->trace_filepath, exec->graph(), tracing_ctx);
+ exec->addObserver(std::move(ctp));
+ }
+
+ return exec;
+}
+
+#ifdef ONERT_TRAIN
+exec::IExecutor *
+ExecutorFactory::create(std::unique_ptr<compiler::train::LoweredTrainableGraph> lowered_graph,
+ const std::shared_ptr<exec::IExecutors> &executors,
+ const ExecutorFactoryArgs &args,
+ const std::shared_ptr<exec::train::optimizer::Optimizer> &optimizer)
+{
+ assert(args.options != nullptr);
+
+ if (args.options->executor != "Linear")
+ throw std::runtime_error("ExecutorFactory: TrainableExecutor supports only 'Linear' now");
+
+ return createTrainableExecutor(std::move(lowered_graph), executors, args, optimizer);
+}
+
+void ExecutorFactory::prepareMigrantTensors(
+ compiler::ILoweredGraph &lowered_graph,
+ const backend::train::TrainableBackendContexts &backend_contexts)
+{
+ train::TensorRegistries tensor_regs{backend_contexts, true};
+
+ lowered_graph.graph().operations().iterate(
+ [&](const ir::OperationIndex &op_ind, const ir::IOperation &op) {
+ auto lower_info = lowered_graph.lower_info().operation.getRawPtr(op_ind);
+ auto &backend_ctx = backend_contexts.at(lower_info->backend());
+ for (auto &&ind :
+ (op.getInputs() + op.getOutputs()) | ir::Remove::DUPLICATED | ir::Remove::UNDEFINED)
+ {
+ // If an Operation's input/output tensor does not have an own tensor object,
+ // it must be using migrant tensors, so find the tensor from other tensor registries and
+ // register it to the current tensor registry if it is portable
+ if (!backend_ctx->tensor_registry()->getITensor(ind))
+ {
+ auto tensor = tensor_regs.getITensor(ind);
+ assert(tensor); // The tensor must have been registered
+ auto ptensor = dynamic_cast<backend::IPortableTensor *>(tensor);
+ if (ptensor)
+ backend_ctx->tensor_registry()->setMigrantTensor(ind, ptensor);
+ }
+ }
+ });
+}
+
+exec::IExecutor *ExecutorFactory::createTrainableExecutor(
+ std::unique_ptr<compiler::train::LoweredTrainableGraph> lowered_graph,
+ const std::shared_ptr<exec::IExecutors> &, const ExecutorFactoryArgs &args,
+ const std::shared_ptr<exec::train::optimizer::Optimizer> &optimizer)
+{
+ const auto options = args.options;
+ const auto tracing_ctx = args.tracing_ctx;
+ auto custom_kernel_builder = args.custom_kernel_builder;
+
+ auto &graph = lowered_graph->graph();
+
+ lowered_graph->trainable_graph().operations().iterate([](const onert::ir::OperationIndex &,
+ const onert::ir::IOperation &op) {
+ try
+ {
+ UNUSED_RELEASE(dynamic_cast<const ir::train::ITrainableOperation &>(op));
+ }
+ catch (std::bad_cast &)
+ {
+ throw std::runtime_error("ExecutorFactory: " + op.name() + " is not trainable operation yet");
+ }
+ });
+
+ // TODO Create context only once instead of replacing
+ backend::train::TrainableBackendContexts tbackend_contexts;
+ backend::BackendContexts base_backend_contexts =
+ createBackendContexts(*lowered_graph, true, custom_kernel_builder);
+
+ // Replace BackendContext with TrainbleBackendContext
+ for (auto &&pair : base_backend_contexts)
+ {
+ auto ctx = pair.second.get();
+ const auto &data = ctx->data();
+
+ // Create partial and trainable graphs
+ auto tgraph = std::make_unique<ir::train::TrainableGraph>(*data.graph);
+ data.graph->operations().iterate(
+ [&](const onert::ir::OperationIndex &op_index, const onert::ir::IOperation &) {
+ const auto &orig_tgraph = lowered_graph->trainable_graph();
+ const auto &trainable_op = orig_tgraph.operation(op_index);
+ auto gen_index = tgraph->replaceOperation(op_index, trainable_op.clone());
+ UNUSED_RELEASE(gen_index);
+ assert(gen_index == op_index);
+ });
+ data.graph->operands().iterate([&](const ir::OperandIndex &index, const ir::Operand &) {
+ const auto &orig_tgraph = lowered_graph->trainable_graph();
+ if (orig_tgraph.derivatives().exist(index))
+ {
+ const auto &deriv = orig_tgraph.derivatives().at(index);
+ auto new_deriv = std::make_unique<ir::Operand>(deriv);
+ auto gen_index = tgraph->addDerivative(index, std::move(new_deriv));
+ UNUSED_RELEASE(gen_index);
+ assert(gen_index == index);
+ }
+ });
+
+ // Remove outputs of whole graph from external_operands
+ auto external_operands = data.external_operands;
+ for (const auto &index : lowered_graph->trainable_graph().getOutputs())
+ {
+ if (external_operands.contains(index))
+ external_operands.remove(index);
+ }
+
+ // Set trainable context data
+ backend::train::TrainableContextData tdata;
+ tdata.tgraph = std::move(tgraph);
+ tdata.op_order = std::move(data.op_order);
+ tdata.external_operands = std::move(external_operands);
+ tdata.operand_layouts = std::move(data.operand_layouts);
+ tdata.custom_kernel_builder = std::move(data.custom_kernel_builder);
+ tdata.is_linear_executor = data.is_linear_executor;
+ tdata.optimizer = optimizer;
+
+ // TODO Remove dynamic_cast
+ try
+ {
+ const auto backend = pair.first;
+ const auto tbackend = dynamic_cast<const backend::train::ITrainableBackend *>(backend);
+ tbackend_contexts.emplace(backend, tbackend->newContext(std::move(tdata)));
+ }
+ catch (const std::bad_cast &)
+ {
+ throw std::runtime_error("ExecutorFactory: Invalid backend - TrainableExecutor does not "
+ "support non-trainble backends");
+ }
+ }
+ base_backend_contexts.clear();
+
+ train::TensorRegistries tensor_regs{tbackend_contexts, true};
+
+ initializeSubgraphIOTensors(
+ *lowered_graph, tbackend_contexts,
+ (lowered_graph->graph().getInputs() + lowered_graph->graph().getOutputs()) |
+ ir::Remove::DUPLICATED | ir::Remove::UNDEFINED);
+
+ // linearize
+ auto order = Linear::linearize(*lowered_graph);
+ Linear::dump(*lowered_graph, order);
+
+ for (auto &&pair : tbackend_contexts)
+ {
+ pair.second->genTensors();
+ }
+
+ for (auto &&pair : tbackend_contexts)
+ {
+ auto tctx = pair.second.get();
+ tctx->genTrainingTensors();
+ }
+
+ prepareMigrantTensors(*lowered_graph, tbackend_contexts);
+
+ // Give some runtime objects to builtin KernelGenerator
+ for (auto &&pair : tbackend_contexts)
+ {
+ auto builtin_context =
+ dynamic_cast<backend::builtin::train::BackendContext *>(pair.second.get());
+ if (builtin_context != nullptr)
+ {
+ auto builtin_kernel_gen = builtin_context->kernel_gen;
+ builtin_kernel_gen->setTensorRegistries(tensor_regs);
+ builtin_kernel_gen->setWholeGraphOutputs(lowered_graph->trainable_graph().getOutputs());
+ }
+ }
+
+ // Adjust the order of backends for the upcoming iteration
+ auto ordered_contexts =
+ onert::orderBackendContext<backend::train::TrainableBackendContext>(tbackend_contexts);
+
+ // TODO Remove this simulation
+ // Simulate the execution for deallocation of tensors
+ std::unordered_map<ir::OperationIndex, DeallocList> dealloc_list_map;
+ {
+ ir::OperandIndexMap<uint32_t> uses_map;
+ ir::OperandIndexSequence constants;
+
+ auto model_io =
+ (graph.getInputs() + graph.getOutputs()) | ir::Remove::UNDEFINED | ir::Remove::DUPLICATED;
+
+ // Prepare scanning
+ graph.operands().iterate([&](const ir::OperandIndex &ind, const ir::Operand &obj) {
+ uses_map[ind] = obj.getUses().size();
+
+ if (obj.isConstant())
+ constants.append(ind);
+ });
+
+ // A trick to consider constants as an execption
+ for (const auto &ind : constants)
+ {
+ uses_map[ind]++;
+ }
+
+ for (const auto op_ind : order)
+ {
+ const auto &op = graph.operations().at(op_ind);
+ auto op_inputs = op.getInputs() | ir::Remove::DUPLICATED | ir::Remove::UNDEFINED;
+ auto op_outputs = op.getOutputs() | ir::Remove::DUPLICATED | ir::Remove::UNDEFINED;
+
+ for (const auto &ind : op_inputs)
+ {
+ const auto &operand = graph.operands().at(ind);
+ assert(uses_map.find(ind) != uses_map.end());
+ assert(uses_map[ind] > 0);
+ uses_map[ind]--;
+ if (uses_map[ind] == 0 && !operand.info().isVariable() && !model_io.contains(ind))
+ {
+ dealloc_list_map[op_ind].emplace_back(tensor_regs.getITensor(ind));
+ }
+ }
+ }
+
+ // Dispose and validate
+ for (const auto &ind : constants)
+ {
+ --uses_map[ind];
+ }
+
+ assert(
+ std::all_of(uses_map.begin(), uses_map.end(),
+ [](std::pair<const ir::OperandIndex, uint32_t> it) { return it.second == 0; }));
+ }
+
+ // Check derivative tensors
+ {
+ // TODO Support multiple subgraphs
+ // Check if the derivative tensors corresponding to inputs of model are nullptr
+ // NOTE The derivative tensors corresponding to inputs of model are for inputs of PermuteLayers
+ // and they are nullptr and because they are meaningless.
+ assert(std::all_of(lowered_graph->trainable_graph().getInputs().begin(),
+ lowered_graph->trainable_graph().getInputs().end(),
+ [&](const auto &input_idx) {
+ return tensor_regs.getDerivativeITensor(input_idx) == nullptr;
+ }));
+
+ // Check if the derivative tensors corresponding to outputs of model exist
+ assert(std::all_of(lowered_graph->trainable_graph().getOutputs().begin(),
+ lowered_graph->trainable_graph().getOutputs().end(),
+ [&](const auto &output_idx) {
+ return tensor_regs.getDerivativeITensor(output_idx) == nullptr;
+ }));
+ }
+
+ train::TrainableCodeMap code_map;
+ // Generate kernels
+ for (auto &&pair : ordered_contexts)
+ {
+ auto codes = pair.second->genKernels();
+ for (auto &&pair : codes)
+ {
+ auto &op_ind = pair.first;
+ auto &tn_seq = pair.second;
+ auto &op = lowered_graph->trainable_graph().operation(op_ind);
+ auto lower_info = lowered_graph->lower_info().operation.getRawPtr(op_ind);
+
+ assert(code_map.find(op_ind) == code_map.end());
+ code_map.insert(
+ {op_ind, train::TrainableCodeAndInfo{op_ind, &op, lower_info, std::move(tn_seq)}});
+ }
+ }
+
+ if (order.size() != code_map.size())
+ {
+ throw std::runtime_error("ExecutorFactory: Some kernels are not generated");
+ }
+
+ auto exec = new exec::train::TrainableExecutor{std::move(lowered_graph),
+ std::move(tbackend_contexts),
+ tensor_regs,
+ std::move(code_map),
+ order,
+ tracing_ctx};
+
+ if (!options->trace_filepath.empty())
{
std::unique_ptr<exec::IExecutionObserver> ctp =
- std::make_unique<exec::TracingObserver>(options.trace_filepath, exec->graph(), tracing_ctx);
+ std::make_unique<exec::TracingObserver>(options->trace_filepath, exec->graph(), tracing_ctx);
exec->addObserver(std::move(ctp));
}
+ // TODO Support MINMAX_H5DUMPER
return exec;
}
+#endif // ONERT_TRAIN
} // namespace compiler
} // namespace onert
diff --git a/runtime/onert/core/src/compiler/ExecutorFactory.h b/runtime/onert/core/src/compiler/ExecutorFactory.h
index f8f989043..cc621bccf 100644
--- a/runtime/onert/core/src/compiler/ExecutorFactory.h
+++ b/runtime/onert/core/src/compiler/ExecutorFactory.h
@@ -20,7 +20,15 @@
#include "TensorRegistries.h"
#include "backend/ITensor.h"
+
+#ifdef ONERT_TRAIN
+#include "backend/train/TrainableBackendContext.h"
+#endif // ONERT_TRAIN
#include "compiler/LoweredGraph.h"
+#ifdef ONERT_TRAIN
+#include "compiler/train/LoweredTrainableGraph.h"
+#include "exec/train/optimizer/Optimizer.h"
+#endif // ONERT_TRAIN
#include "exec/IExecutors.h"
#include <deque>
@@ -31,6 +39,15 @@ namespace onert
namespace compiler
{
+// TODO Change to a better name
+struct ExecutorFactoryArgs
+{
+ const util::TracingCtx *tracing_ctx;
+ const compiler::CompilerOptions *options;
+ ir::ModelIndex model_index;
+ std::shared_ptr<backend::custom::IKernelBuilder> custom_kernel_builder;
+};
+
class ExecutorFactory
{
public:
@@ -38,16 +55,22 @@ public:
public:
exec::IExecutor *create(std::unique_ptr<compiler::LoweredGraph> lowered_graph,
- const util::TracingCtx *tracing_ctx,
- const compiler::CompilerOptions &options,
const std::shared_ptr<exec::IExecutors> &executors,
- const ir::ModelIndex &index);
+ const ExecutorFactoryArgs &args);
+
+#ifdef ONERT_TRAIN
+ // TODO Unify create()
+ exec::IExecutor *create(std::unique_ptr<compiler::train::LoweredTrainableGraph> lowered_graph,
+ const std::shared_ptr<exec::IExecutors> &executors,
+ const ExecutorFactoryArgs &args,
+ const std::shared_ptr<exec::train::optimizer::Optimizer> &optimizer);
+#endif // ONERT_TRAIN
private:
ExecutorFactory();
private:
- static void prepareMigrantTensors(compiler::LoweredGraph &lowered_graph,
+ static void prepareMigrantTensors(compiler::ILoweredGraph &lowered_graph,
const backend::BackendContexts &backend_contexts);
static void prepareBuiltinBackend(const TensorRegistries &tensor_regs,
const std::shared_ptr<exec::IExecutors> &executors,
@@ -56,22 +79,31 @@ private:
static std::deque<std::pair<const backend::Backend *, backend::BackendContext *>>
orderBackendContext(const backend::BackendContexts &backend_contexts);
- static exec::IExecutor *createLinearExecutor(
- std::unique_ptr<compiler::LoweredGraph> lowered_graph, const util::TracingCtx *tracing_ctx,
- const compiler::CompilerOptions &options, const std::shared_ptr<exec::IExecutors> &executors,
- const ir::ModelIndex &index);
- static exec::IExecutor *createDataflowExecutor(
- std::unique_ptr<compiler::LoweredGraph> lowered_graph, const util::TracingCtx *tracing_ctx,
- const compiler::CompilerOptions &options, const std::shared_ptr<exec::IExecutors> &executors,
- const ir::ModelIndex &index, bool parallel);
+ static exec::IExecutor *
+ createLinearExecutor(std::unique_ptr<compiler::LoweredGraph> lowered_graph,
+ const std::shared_ptr<exec::IExecutors> &executors,
+ const ExecutorFactoryArgs &args);
+ static exec::IExecutor *
+ createDataflowExecutor(std::unique_ptr<compiler::LoweredGraph> lowered_graph,
+ const std::shared_ptr<exec::IExecutors> &executors,
+ const ExecutorFactoryArgs &args, bool parallel);
+#ifdef ONERT_TRAIN
+ // TODO Unify prepareMigrantTensors
+ static void
+ prepareMigrantTensors(compiler::ILoweredGraph &lowered_graph,
+ const backend::train::TrainableBackendContexts &backend_contexts);
+ static exec::IExecutor *
+ createTrainableExecutor(std::unique_ptr<compiler::train::LoweredTrainableGraph> lowered_graph,
+ const std::shared_ptr<exec::IExecutors> &executors,
+ const ExecutorFactoryArgs &args,
+ const std::shared_ptr<exec::train::optimizer::Optimizer> &optimizer);
+#endif // ONERT_TRAIN
private:
std::unordered_map<
- std::string,
- std::function<exec::IExecutor *(
- std::unique_ptr<compiler::LoweredGraph>, const util::TracingCtx *tracing_ctx,
- const compiler::CompilerOptions &options, const std::shared_ptr<exec::IExecutors> &executors,
- const ir::ModelIndex &index)>>
+ std::string, std::function<exec::IExecutor *(std::unique_ptr<compiler::LoweredGraph>,
+ const std::shared_ptr<exec::IExecutors> &executors,
+ const ExecutorFactoryArgs &args)>>
_map;
};
diff --git a/runtime/onert/core/src/compiler/Fp32ToFp16Converter.cc b/runtime/onert/core/src/compiler/Fp32ToFp16Converter.cc
index fdf4e24f0..ce9b09c2d 100644
--- a/runtime/onert/core/src/compiler/Fp32ToFp16Converter.cc
+++ b/runtime/onert/core/src/compiler/Fp32ToFp16Converter.cc
@@ -776,7 +776,7 @@ Fp32ToFp16Converter::InputToOpSeqs Fp32ToFp16Converter::prepareInputToOpSeqs() c
InputToOpSeqs input_to_op_seqs;
op_seqs.iterate([&](const ir::OpSequenceIndex &op_seq_idx, const ir::OpSequence &op_seq) {
- for (auto input : op_seq.getInputs() | ir::Remove::UNDEFINED)
+ for (auto &&input : op_seq.getInputs() | ir::Remove::UNDEFINED)
{
auto it = input_to_op_seqs.find(input);
if (it == input_to_op_seqs.end())
@@ -862,7 +862,7 @@ void Fp32ToFp16Converter::manipulateContiguousOpSequences(
// |
// [OPERATION] // op_seq_ind_next_to_fp16
//
- for (auto it : opseq_map_to_delete)
+ for (auto &&it : opseq_map_to_delete)
{
// fp16_to_fp32's input/output num is always 1
auto &op_seq_ind_fp16_to_fp32 = it.first;
diff --git a/runtime/onert/core/src/compiler/HEScheduler.cc b/runtime/onert/core/src/compiler/HEScheduler.cc
index 65fd4cd77..f662ef5b9 100644
--- a/runtime/onert/core/src/compiler/HEScheduler.cc
+++ b/runtime/onert/core/src/compiler/HEScheduler.cc
@@ -28,7 +28,7 @@ namespace
using namespace onert;
-uint32_t getOperationsFlattenedIOSize(const ir::Graph &graph, const ir::Operation &node)
+uint32_t getOperationsFlattenedIOSize(const ir::Graph &graph, const ir::IOperation &node)
{
uint32_t size = 0;
for (const auto &ind :
@@ -39,7 +39,7 @@ uint32_t getOperationsFlattenedIOSize(const ir::Graph &graph, const ir::Operatio
return size;
}
-bool isQuant(const ir::Graph &graph, const ir::Operation &node)
+bool isQuant(const ir::Graph &graph, const ir::IOperation &node)
{
for (const auto &input : node.getInputs() | ir::Remove::UNDEFINED)
{
@@ -52,14 +52,14 @@ bool isQuant(const ir::Graph &graph, const ir::Operation &node)
return false;
}
-bool isWorkaroundSkip(const ir::Graph &, const backend::Backend *, const ir::Operation &, bool)
+bool isWorkaroundSkip(const ir::Graph &, const backend::Backend *, const ir::IOperation &, bool)
{
// Now, there is no workaround
return false;
}
// if a node can be merged into op_seq
-bool isMergeable(const ir::Graph &graph, const ir::Operation &node)
+bool isMergeable(const ir::Graph &graph, const ir::IOperation &node)
{
size_t prev_op_cnt = 0;
for (const auto &input : node.getInputs() | ir::Remove::UNDEFINED)
@@ -137,7 +137,7 @@ void HEScheduler::scheduleShufflingBackends()
}
}
-bool HEScheduler::isNodeProfiled(const ir::Operation &node)
+bool HEScheduler::isNodeProfiled(const ir::IOperation &node)
{
const bool quant = isQuant(*_graph, node);
const auto size = getOperationsFlattenedIOSize(*_graph, node);
@@ -207,7 +207,7 @@ std::unique_ptr<compiler::BackendResolver> HEScheduler::schedule(const ir::Graph
{
// Check if profiling info about all backend/node pairs already exists
bool all_nodes_are_profiled = true;
- _graph->operations().iterate([&](const ir::OperationIndex &, const ir::Operation &op) {
+ _graph->operations().iterate([&](const ir::OperationIndex &, const ir::IOperation &op) {
if (all_nodes_are_profiled)
all_nodes_are_profiled = isNodeProfiled(op);
});
@@ -224,7 +224,7 @@ std::unique_ptr<compiler::BackendResolver> HEScheduler::schedule(const ir::Graph
ir::OperationIndexMap<bool> visited;
graph.operations().iterate(
- [&](const ir::OperationIndex &index, const ir::Operation &) { visited[index] = false; });
+ [&](const ir::OperationIndex &index, const ir::IOperation &) { visited[index] = false; });
// for each task select the backend with the smallest earliest finishing time(eft)
for (const auto &rank : _rank_to_op)
{
@@ -258,7 +258,7 @@ int64_t HEScheduler::getPermuteTime(const backend::Backend *src_backend,
return size / 400;
}
-int64_t HEScheduler::tryBackend(const ir::Operation &node, const backend::Backend *backend)
+int64_t HEScheduler::tryBackend(const ir::IOperation &node, const backend::Backend *backend)
{
// if there is no profiling info don't use this backend during scheduling
if (!_is_profiling_mode)
@@ -297,10 +297,10 @@ void HEScheduler::makeRank()
VERBOSE(HEScheduler::makeRank) << "task prioritizing" << std::endl;
_graph->operations().iterate(
- [&](const ir::OperationIndex &index, const ir::Operation &) { DFSMaxRank(index); });
+ [&](const ir::OperationIndex &index, const ir::IOperation &) { DFSMaxRank(index); });
// Check that ranks are calculated for all operations(nodes)
- _graph->operations().iterate([&](const ir::OperationIndex &index, const ir::Operation &) {
+ _graph->operations().iterate([&](const ir::OperationIndex &index, const ir::IOperation &) {
UNUSED_RELEASE(index);
assert(_op_to_rank->find(index) != _op_to_rank->end());
});
@@ -564,7 +564,7 @@ HEScheduler::ESTAndExecTime(const backend::Backend *backend, const ir::Operation
return {prev_op_ft, exec_time};
}
-int64_t HEScheduler::predMaxEFT(const backend::Backend *backend, const ir::Operation &node,
+int64_t HEScheduler::predMaxEFT(const backend::Backend *backend, const ir::IOperation &node,
std::multimap<int64_t, int64_t> &transfer_st_exec_time)
{
int64_t max_pred_eft = 0;
diff --git a/runtime/onert/core/src/compiler/HEScheduler.h b/runtime/onert/core/src/compiler/HEScheduler.h
index 18ea388fd..df6c07926 100644
--- a/runtime/onert/core/src/compiler/HEScheduler.h
+++ b/runtime/onert/core/src/compiler/HEScheduler.h
@@ -58,7 +58,7 @@ public:
_is_profiling_mode{options.he_profiling_mode}, _is_linear_exec{options.executor == "Linear"},
_is_parallel_exec{options.executor == "Parallel"}
{
- for (auto entry : backends)
+ for (auto &&entry : backends)
{
if (entry->config()->id() == backend::builtin::Config::ID)
continue;
@@ -88,7 +88,7 @@ public:
std::shared_ptr<ir::OperationIndexMap<int64_t>> getIndexedRanks() { return _op_to_rank; }
private:
- bool isNodeProfiled(const ir::Operation &);
+ bool isNodeProfiled(const ir::IOperation &);
bool schedule(const ir::OperationIndex &, const backend::Backend *parent_backend);
/**
@@ -115,7 +115,7 @@ private:
*
* @return earliest finishing time of parent nodes
*/
- int64_t predMaxEFT(const backend::Backend *backend, const ir::Operation &node,
+ int64_t predMaxEFT(const backend::Backend *backend, const ir::IOperation &node,
std::multimap<int64_t, int64_t> &transfer_st_exec_time);
void makeRank();
@@ -146,7 +146,7 @@ private:
void scheduleShufflingBackends();
- int64_t tryBackend(const ir::Operation &node, const backend::Backend *backend);
+ int64_t tryBackend(const ir::IOperation &node, const backend::Backend *backend);
/**
* @brief Schedule a node and its successor until:
diff --git a/runtime/onert/core/src/compiler/HEScheduler.test.cc b/runtime/onert/core/src/compiler/HEScheduler.test.cc
index 589331b49..1654bfc8b 100644
--- a/runtime/onert/core/src/compiler/HEScheduler.test.cc
+++ b/runtime/onert/core/src/compiler/HEScheduler.test.cc
@@ -43,7 +43,7 @@ struct MockConfigCPU : public IConfig
std::string id() override { return "cpu"; }
bool initialize() override { return true; };
bool supportPermutation() override { return false; }
- Layout supportLayout(const Operation &, Layout) override { return Layout::UNKNOWN; }
+ Layout supportLayout(const IOperation &, Layout) override { return Layout::UNKNOWN; }
bool supportDynamicTensor() override { return false; }
bool supportFP16() override { return false; }
};
@@ -70,7 +70,7 @@ struct MockConfigGPU : public IConfig
std::string id() override { return "gpu"; }
bool initialize() override { return true; };
bool supportPermutation() override { return false; }
- ir::Layout supportLayout(const ir::Operation &, ir::Layout) override
+ ir::Layout supportLayout(const ir::IOperation &, ir::Layout) override
{
return ir::Layout::UNKNOWN;
}
@@ -92,7 +92,7 @@ struct MockConfigNPU : public IConfig
std::string id() override { return "npu"; }
bool initialize() override { return true; };
bool supportPermutation() override { return false; }
- ir::Layout supportLayout(const ir::Operation &, ir::Layout) override
+ ir::Layout supportLayout(const ir::IOperation &, ir::Layout) override
{
return ir::Layout::UNKNOWN;
}
diff --git a/runtime/onert/core/src/compiler/Linear.cc b/runtime/onert/core/src/compiler/Linear.cc
index f85b8d1bd..4dbe229c8 100644
--- a/runtime/onert/core/src/compiler/Linear.cc
+++ b/runtime/onert/core/src/compiler/Linear.cc
@@ -28,16 +28,16 @@ namespace compiler
{
// TODO(easy) Change the LoweredGraph param to Graph
-std::vector<ir::OperationIndex> Linear::linearize(const compiler::LoweredGraph &lowered_graph)
+std::vector<ir::OperationIndex> Linear::linearize(const compiler::ILoweredGraph &lowered_graph)
{
return lowered_graph.graph().topolSortOperations();
}
// TODO(easy) Change the LoweredGraph param to Graph
-void Linear::dump(const compiler::LoweredGraph &lowered_graph,
+void Linear::dump(const compiler::ILoweredGraph &lowered_graph,
const std::vector<ir::OperationIndex> &order)
{
- for (const auto ind : order)
+ for (const auto &ind : order)
{
// TODO Could logging system can handle this? (Inserting prefix for each line)
std::istringstream iss{dumper::text::formatOperation(lowered_graph.graph(), ind)};
diff --git a/runtime/onert/core/src/compiler/Linear.h b/runtime/onert/core/src/compiler/Linear.h
index 9ac9a0139..4f92dc88d 100644
--- a/runtime/onert/core/src/compiler/Linear.h
+++ b/runtime/onert/core/src/compiler/Linear.h
@@ -21,7 +21,7 @@
#include <memory>
#include "ir/Index.h"
-#include "compiler/LoweredGraph.h"
+#include "compiler/ILoweredGraph.h"
namespace onert
{
@@ -31,8 +31,8 @@ namespace compiler
class Linear
{
public:
- static std::vector<ir::OperationIndex> linearize(const compiler::LoweredGraph &lowered_graph);
- static void dump(const compiler::LoweredGraph &lowered_graph,
+ static std::vector<ir::OperationIndex> linearize(const compiler::ILoweredGraph &lowered_graph);
+ static void dump(const compiler::ILoweredGraph &lowered_graph,
const std::vector<ir::OperationIndex> &order);
};
diff --git a/runtime/onert/core/src/compiler/LoweredGraph.cc b/runtime/onert/core/src/compiler/LoweredGraph.cc
index d53d0ed00..46a45e44a 100644
--- a/runtime/onert/core/src/compiler/LoweredGraph.cc
+++ b/runtime/onert/core/src/compiler/LoweredGraph.cc
@@ -49,7 +49,7 @@ void LoweredGraph::lowerGraph(const CompilerOptions &options)
// Build backend contexts
auto &backend_manager = BackendManager::get();
// Create contexts for other backends
- for (auto backend_str : options.backend_list)
+ for (auto &&backend_str : options.backend_list)
{
backend_manager.loadBackend(backend_str);
auto backend = backend_manager.get(backend_str);
@@ -100,9 +100,9 @@ void LoweredGraph::lowerGraph(const CompilerOptions &options)
pass::PassRunner{}.append(std::make_unique<pass::PermutationEliminationPass>(*this)).run();
VERBOSE(LoweredGraph) << "Dump after all the passes" << std::endl;
- for (auto operand : _graph.getInputs())
+ for (auto &&operand : _graph.getInputs())
VERBOSE(LoweredGraph) << "Graph Input : " << operand << std::endl;
- for (auto operand : _graph.getOutputs())
+ for (auto &&operand : _graph.getOutputs())
VERBOSE(LoweredGraph) << "Graph Output : " << operand << std::endl;
dumper::text::dumpLoweredGraph(*this);
@@ -121,8 +121,8 @@ void LoweredGraph::makeLowerInfo(const compiler::BackendResolver &backend_resolv
});
// Set operand lower info using assigned backends to operations
- _graph.operations().iterate([&](const ir::OperationIndex &op_ind, const ir::Operation &) {
- const ir::Operation &op = _graph.operations().at(op_ind);
+ _graph.operations().iterate([&](const ir::OperationIndex &op_ind, const ir::IOperation &) {
+ const ir::IOperation &op = _graph.operations().at(op_ind);
auto backend = backend_resolver.getBackend(op_ind);
if (!backend)
{
@@ -135,12 +135,12 @@ void LoweredGraph::makeLowerInfo(const compiler::BackendResolver &backend_resolv
// TODO Change setting layout of each backend at another place
auto backend_layout = backend->config()->supportLayout(op, frontend_layout);
- for (auto ind : op.getInputs() | ir::Remove::UNDEFINED)
+ for (auto &&ind : op.getInputs() | ir::Remove::UNDEFINED)
{
auto &operand_li = lower_info().operand.at(ind);
operand_li.addUsePermuteFactor(PermuteFactor{backend, backend_layout});
}
- for (auto ind : op.getOutputs() | ir::Remove::UNDEFINED)
+ for (auto &&ind : op.getOutputs() | ir::Remove::UNDEFINED)
{
auto &operand_li = lower_info().operand.at(ind);
operand_li.addDefPermuteFactor(PermuteFactor{backend, backend_layout});
@@ -152,13 +152,13 @@ void LoweredGraph::makeLowerInfo(const compiler::BackendResolver &backend_resolv
// Handle graph inputs and outputs
const auto builtin_backend = BackendManager::get().getBuiltin();
auto factor = PermuteFactor{builtin_backend, _graph.layout()};
- for (auto index : _graph.getInputs() | ir::Remove::UNDEFINED)
+ for (auto &&index : _graph.getInputs() | ir::Remove::UNDEFINED)
{
auto &operand_li = lower_info().operand.at(index);
assert(operand_li.def_factors().empty());
operand_li.addDefPermuteFactor(factor);
}
- for (auto index : _graph.getOutputs() | ir::Remove::UNDEFINED)
+ for (auto &&index : _graph.getOutputs() | ir::Remove::UNDEFINED)
{
auto &operand_li = lower_info().operand.at(index);
operand_li.addUsePermuteFactor(factor);
@@ -204,7 +204,7 @@ void LoweredGraph::dumpLowerInfo()
auto factors_to_string = [](const PermuteFactorSet &factors) {
std::string str;
- for (auto factor : factors)
+ for (auto &&factor : factors)
{
str += factor.backend()->config()->id();
str += "(" + to_string(factor.layout()) + ")";
@@ -216,7 +216,7 @@ void LoweredGraph::dumpLowerInfo()
auto operation_index_set_to_string = [](const ir::OperationIndexSet &operations) {
std::stringstream sstream;
sstream << "{ ";
- for (auto op : operations)
+ for (auto &&op : operations)
sstream << op << " ";
sstream << "}";
return sstream.str();
diff --git a/runtime/onert/core/src/compiler/ManualScheduler.cc b/runtime/onert/core/src/compiler/ManualScheduler.cc
index 621f0c7b7..ccd08893f 100644
--- a/runtime/onert/core/src/compiler/ManualScheduler.cc
+++ b/runtime/onert/core/src/compiler/ManualScheduler.cc
@@ -42,7 +42,7 @@ std::unique_ptr<BackendResolver> ManualScheduler::schedule(const ir::Graph &grap
// This fallback will be used in case that `backend_for_all` is unavailable
auto fallback = [&]() -> const backend::Backend * {
- for (auto backend_id : _options.backend_list)
+ for (auto &&backend_id : _options.backend_list)
{
auto backend = resolveBackend(backend_id);
if (backend)
@@ -58,7 +58,7 @@ std::unique_ptr<BackendResolver> ManualScheduler::schedule(const ir::Graph &grap
VERBOSE(ManualScheduler) << "Default backend for all ops: " << backend_all->config()->id()
<< std::endl;
- graph.operations().iterate([&](const ir::OperationIndex &index, const ir::Operation &) {
+ graph.operations().iterate([&](const ir::OperationIndex &index, const ir::IOperation &) {
backend_resolver->setBackend(index, backend_all);
});
@@ -71,7 +71,7 @@ std::unique_ptr<BackendResolver> ManualScheduler::schedule(const ir::Graph &grap
// By default, Custom uses cpu backend
op_type_map[ir::OpCode::Custom] = BackendManager::get().get("cpu");
- graph.operations().iterate([&](const ir::OperationIndex &index, const ir::Operation &operation) {
+ graph.operations().iterate([&](const ir::OperationIndex &index, const ir::IOperation &operation) {
auto itr = op_type_map.find(operation.opcode());
if (itr != op_type_map.end())
{
diff --git a/runtime/onert/core/src/compiler/MultiModelCompiler.cc b/runtime/onert/core/src/compiler/MultiModelCompiler.cc
index fea6a7f25..141fdfe09 100644
--- a/runtime/onert/core/src/compiler/MultiModelCompiler.cc
+++ b/runtime/onert/core/src/compiler/MultiModelCompiler.cc
@@ -16,6 +16,7 @@
#include "MultiModelCompiler.h"
+#include "CompilerHelpers.h"
#include "ExecutorFactory.h"
#include "ShapeValidator.h"
#include "pass/ConstantOutputPass.h"
@@ -30,6 +31,7 @@
#include "compiler/StaticShapeInferer.h"
#include <misc/string_helpers.h>
+#include <misc/polymorphic_downcast.h>
namespace onert
{
@@ -53,7 +55,7 @@ std::shared_ptr<CompilerArtifact> MultiModelCompiler::compile(void)
/***************************************************
* Prepare compilation phase
***************************************************/
- for (auto options : _voptions)
+ for (auto &&options : _voptions)
{
if (!options)
throw std::runtime_error{"Empty compile option"};
@@ -63,6 +65,9 @@ std::shared_ptr<CompilerArtifact> MultiModelCompiler::compile(void)
if (options->he_profiling_mode)
throw std::runtime_error("NYI: Profiling mode for multiple model is not supported yet");
+ if (!options->minmax_filepath.empty())
+ throw std::runtime_error("Recording minmax is not supported for multiple models");
+
options->forceInternalOptions();
options->verboseOptions();
}
@@ -74,7 +79,15 @@ std::shared_ptr<CompilerArtifact> MultiModelCompiler::compile(void)
for (uint16_t i = 0; i < model_count; i++)
{
- _nnpkg->model(ir::ModelIndex{i})->iterate([&](const ir::SubgraphIndex &, ir::Graph &subg) {
+ if (!_nnpkg->model(ir::ModelIndex{i})->hasOnly<ir::Graph>())
+ throw std::runtime_error("MultiModelCompiler can only compile models for inference.");
+ }
+
+ for (uint16_t i = 0; i < model_count; i++)
+ {
+ _nnpkg->model(ir::ModelIndex{i})->iterate([&](const ir::SubgraphIndex &, ir::IGraph &graph) {
+ auto &subg = nnfw::misc::polymorphic_downcast<ir::Graph &>(graph);
+
// Mandatory passes
pass::PassRunner{}
.append(std::make_unique<pass::ConstantOutputPass>(subg))
@@ -100,6 +113,15 @@ std::shared_ptr<CompilerArtifact> MultiModelCompiler::compile(void)
// Model edge context: copy model edge context
auto model_edges = std::make_unique<ir::ModelEdges>(_nnpkg->model_edges());
+ // Custom kernels
+ std::unordered_map<ir::ModelIndex, std::shared_ptr<backend::custom::IKernelBuilder>>
+ custom_kernel_builders;
+ for (uint16_t i = 0; i < model_count; i++)
+ {
+ auto const model_index = ir::ModelIndex{i};
+ custom_kernel_builders[model_index] = _nnpkg->model(model_index)->getKernelBuilder();
+ }
+
// Lower: Assign backend
std::unordered_map<ir::ModelIndex,
std::unordered_map<ir::SubgraphIndex, std::unique_ptr<compiler::LoweredGraph>>>
@@ -110,7 +132,9 @@ std::shared_ptr<CompilerArtifact> MultiModelCompiler::compile(void)
auto const model_index = ir::ModelIndex{i};
auto model = _nnpkg->model(model_index);
- model->iterate([&](const ir::SubgraphIndex &subg_index, ir::Graph &subg) {
+ model->iterate([&](const ir::SubgraphIndex &subg_index, ir::IGraph &graph) {
+ auto &subg = nnfw::misc::polymorphic_downcast<ir::Graph &>(graph);
+
dot_dumper.dump(subg,
nnfw::misc::str("before_lower_model-", i, "-subg-", subg_index.value()));
// Lower: Assign backend
@@ -146,7 +170,7 @@ std::shared_ptr<CompilerArtifact> MultiModelCompiler::compile(void)
// Run the StaticShapeInfer of primary subg. All child StaticShapeInferers are called
// recursively
std::unordered_map<ir::SubgraphIndex, std::unique_ptr<StaticShapeInferer>> inferers =
- StaticShapeInferer::createStaticShapeInferers(model_lsubgs);
+ createStaticShapeInferers(model_lsubgs);
const auto primary_subg_idx = ir::SubgraphIndex{0};
inferers.at(primary_subg_idx)->infer();
@@ -194,11 +218,15 @@ std::shared_ptr<CompilerArtifact> MultiModelCompiler::compile(void)
ir::OperationDumper dumper("Executor generation of Subgraph " +
std::to_string(subg_index.value()));
lowered_subg->graph().operations().iterate(
- [&](const ir::OperationIndex &, const ir::Operation &op) { op.accept(dumper); });
-
- auto &options = *_voptions[model_index.value()];
- auto executor = std::unique_ptr<exec::IExecutor>{ExecutorFactory::get().create(
- std::move(lowered_subg), tracing_ctx.get(), options, executors, model_index)};
+ [&](const ir::OperationIndex &, const ir::IOperation &op) { op.accept(dumper); });
+
+ ExecutorFactoryArgs args;
+ args.tracing_ctx = tracing_ctx.get();
+ args.options = _voptions[model_index.value()];
+ args.model_index = model_index;
+ args.custom_kernel_builder = custom_kernel_builders[model_index];
+ auto executor = std::unique_ptr<exec::IExecutor>{
+ ExecutorFactory::get().create(std::move(lowered_subg), executors, args)};
executor->setIndexedRanks(indexed_ranks);
executors->emplace(model_index, subg_index, std::move(executor));
}
diff --git a/runtime/onert/core/src/compiler/MultiModelCompiler.h b/runtime/onert/core/src/compiler/MultiModelCompiler.h
index 89af664f8..b282a5087 100644
--- a/runtime/onert/core/src/compiler/MultiModelCompiler.h
+++ b/runtime/onert/core/src/compiler/MultiModelCompiler.h
@@ -59,12 +59,6 @@ public:
std::shared_ptr<CompilerArtifact> compile(void);
private:
- std::shared_ptr<ir::Graph> &primary_subgraph()
- {
- return _nnpkg->primary_model()->at(ir::SubgraphIndex{0});
- }
-
-private:
std::shared_ptr<ir::NNPkg> _nnpkg;
std::vector<CompilerOptions *> _voptions;
};
diff --git a/runtime/onert/core/src/compiler/ShapeValidator.cc b/runtime/onert/core/src/compiler/ShapeValidator.cc
index 8c6421744..3e940f037 100644
--- a/runtime/onert/core/src/compiler/ShapeValidator.cc
+++ b/runtime/onert/core/src/compiler/ShapeValidator.cc
@@ -52,7 +52,7 @@ void ShapeValidator::checkUnaryOp(const ir::Operation &node)
void ShapeValidator::operator()()
{
_graph.operations().iterate(
- [&](const ir::OperationIndex &, const ir::Operation &node) { node.accept(*this); });
+ [&](const ir::OperationIndex &, const ir::IOperation &node) { node.accept(*this); });
}
void ShapeValidator::visit(const ir::operation::BatchMatMul &node)
diff --git a/runtime/onert/core/src/compiler/StaticShapeInferer.cc b/runtime/onert/core/src/compiler/StaticShapeInferer.cc
index 25747d950..a25b326f1 100644
--- a/runtime/onert/core/src/compiler/StaticShapeInferer.cc
+++ b/runtime/onert/core/src/compiler/StaticShapeInferer.cc
@@ -99,10 +99,10 @@ void StaticShapeInferer::infer()
}
}
-bool StaticShapeInferer::checkDynamicInput(const ir::Operation &op)
+bool StaticShapeInferer::checkDynamicInput(const ir::IOperation &op)
{
const auto &operands = _lowered_subg->graph().operands();
- for (auto input_idx : op.getInputs() | ir::Remove::UNDEFINED | ir::Remove::DUPLICATED)
+ for (auto &&input_idx : op.getInputs() | ir::Remove::UNDEFINED | ir::Remove::DUPLICATED)
{
if (operands.at(input_idx).info().isDynamic())
{
@@ -113,10 +113,10 @@ bool StaticShapeInferer::checkDynamicInput(const ir::Operation &op)
return false;
}
-bool StaticShapeInferer::checkDynamicOutput(const ir::Operation &op)
+bool StaticShapeInferer::checkDynamicOutput(const ir::IOperation &op)
{
auto &operands = _lowered_subg->graph().operands();
- for (auto output_idx : op.getOutputs() | ir::Remove::UNDEFINED)
+ for (auto &&output_idx : op.getOutputs() | ir::Remove::UNDEFINED)
{
if (operands.at(output_idx).info().isDynamic())
{
@@ -126,10 +126,10 @@ bool StaticShapeInferer::checkDynamicOutput(const ir::Operation &op)
return false;
}
-void StaticShapeInferer::setDynamicOutput(const ir::Operation &op)
+void StaticShapeInferer::setDynamicOutput(const ir::IOperation &op)
{
auto &operands = _lowered_subg->graph().operands();
- for (auto output_idx : op.getOutputs() | ir::Remove::UNDEFINED)
+ for (auto &&output_idx : op.getOutputs() | ir::Remove::UNDEFINED)
{
operands.at(output_idx).info().setDynamic();
}
@@ -192,7 +192,7 @@ void StaticShapeInferer::dump()
std::unordered_map<ir::SubgraphIndex, std::unique_ptr<StaticShapeInferer>>
StaticShapeInferer::createStaticShapeInferers(
- const std::unordered_map<ir::SubgraphIndex, std::unique_ptr<LoweredGraph>> &lowered_subgs)
+ const std::unordered_map<ir::SubgraphIndex, ILoweredGraph *> &lowered_subgs)
{
// Allocate StaticShapeInferer per each subgraph
std::unordered_map<ir::SubgraphIndex, std::unique_ptr<StaticShapeInferer>> inferers;
@@ -200,7 +200,7 @@ StaticShapeInferer::createStaticShapeInferers(
{
const auto &subg_index = pair.first;
auto &lowered_subg = pair.second;
- inferers[subg_index] = std::make_unique<StaticShapeInferer>(lowered_subg.get());
+ inferers[subg_index] = std::make_unique<StaticShapeInferer>(lowered_subg);
}
// Append observers in all StaticShapeInferers
@@ -211,7 +211,7 @@ StaticShapeInferer::createStaticShapeInferers(
// TODO: Change this iteration for all to controlflow iteration
lowered_subg->graph().operations().iterate(
- [&](const ir::OperationIndex &, const ir::Operation &op) {
+ [&](const ir::OperationIndex &, const ir::IOperation &op) {
// A Function to append child inferers. These make it possible for a StaticShapeInferer to
// call StaticShapeInferes of child subgraphs recursively
auto appendChildInferer = [&](const ir::SubgraphIndex &child_subg_idx) {
@@ -251,7 +251,9 @@ StaticShapeInferer::createStaticShapeInferers(
// Append Observers in a StaticShapeInferer
if (op.opcode() == ir::OpCode::If)
{
- const auto &if_op = nnfw::misc::polymorphic_downcast<const ir::operation::If &>(op);
+ // TODO Remove dynamic_cast
+ // An virtual base class cannot be downcasted by static_cast
+ const auto &if_op = dynamic_cast<const ir::operation::If &>(op);
appendChildInferer(if_op.param().then_subg_index);
appendChildInferer(if_op.param().else_subg_index);
@@ -263,7 +265,8 @@ StaticShapeInferer::createStaticShapeInferers(
}
else if (op.opcode() == ir::OpCode::While)
{
- const auto &while_op = nnfw::misc::polymorphic_downcast<const ir::operation::While &>(op);
+ // TODO Remove dynamic_cast
+ const auto &while_op = dynamic_cast<const ir::operation::While &>(op);
appendChildInferer(while_op.param().cond_subg_index);
appendChildInferer(while_op.param().body_subg_index);
@@ -602,6 +605,13 @@ void StaticShapeInferer::visit(const ir::operation::L2Normalization &op)
handleSimpleUnaryOp(op, op.getInputs().at(ir::operation::L2Normalization::Input::INPUT));
}
+void StaticShapeInferer::visit(const ir::operation::Loss &)
+{
+ // TODO Consider SparseCategoricalCrossentropy case
+
+ // TODO Consider output shape in case of reduction option
+}
+
void StaticShapeInferer::visit(const ir::operation::LSTM &op)
{
auto &operands = _lowered_subg->graph().operands();
@@ -1119,7 +1129,7 @@ void StaticShapeInferer::visit(const ir::operation::Split &op)
auto outputs = op.getOutputs();
if (!axis.isConstant())
{
- for (auto output_idx : outputs)
+ for (auto &&output_idx : outputs)
{
ir::Operand &output = operands.at(output_idx);
output.info().setDynamic();
@@ -1137,7 +1147,7 @@ void StaticShapeInferer::visit(const ir::operation::Split &op)
ir::Shape new_shape =
shape_inference::inferSplitShape(input.info().shape(), axis_value, num_splits);
- for (auto output_idx : outputs)
+ for (auto &&output_idx : outputs)
{
ir::Operand &output = operands.at(output_idx);
output.info().shape(new_shape);
diff --git a/runtime/onert/core/src/compiler/pass/ConstantInsertionPass.cc b/runtime/onert/core/src/compiler/pass/ConstantInsertionPass.cc
index 89dd303d4..a6590b13f 100644
--- a/runtime/onert/core/src/compiler/pass/ConstantInsertionPass.cc
+++ b/runtime/onert/core/src/compiler/pass/ConstantInsertionPass.cc
@@ -28,14 +28,14 @@ namespace compiler
namespace pass
{
-void ConstantInsertionPass::callback(const ir::OperationIndex &node_index, ir::Operation &node)
+void ConstantInsertionPass::callback(const ir::OperationIndex &node_index, ir::IOperation &node)
{
const auto op_lower_info = _lowered_graph.lower_info().operation.getRawPtr(node_index);
const auto backend = op_lower_info->backend();
const auto layout = op_lower_info->layout();
const auto factor = PermuteFactor{backend, layout};
- for (const auto input : node.getInputs() | ir::Remove::DUPLICATED | ir::Remove::UNDEFINED)
+ for (const auto &input : node.getInputs() | ir::Remove::DUPLICATED | ir::Remove::UNDEFINED)
{
auto &object = _graph.operands().at(input);
diff --git a/runtime/onert/core/src/compiler/pass/ConstantInsertionPass.h b/runtime/onert/core/src/compiler/pass/ConstantInsertionPass.h
index 4911ace2f..d5b9aa14e 100644
--- a/runtime/onert/core/src/compiler/pass/ConstantInsertionPass.h
+++ b/runtime/onert/core/src/compiler/pass/ConstantInsertionPass.h
@@ -39,7 +39,7 @@ public:
std::string id() final { return "ConstantInsertionPass"; }
public:
- void callback(const ir::OperationIndex &index, ir::Operation &node) final;
+ void callback(const ir::OperationIndex &index, ir::IOperation &node) final;
private:
struct ReplaceKey
diff --git a/runtime/onert/core/src/compiler/pass/ConstantLoweringPass.cc b/runtime/onert/core/src/compiler/pass/ConstantLoweringPass.cc
index 6ed154548..32e32d0ef 100644
--- a/runtime/onert/core/src/compiler/pass/ConstantLoweringPass.cc
+++ b/runtime/onert/core/src/compiler/pass/ConstantLoweringPass.cc
@@ -29,7 +29,7 @@ namespace compiler
namespace pass
{
-void ConstantLoweringPass::callback(const ir::OperationIndex &node_index, ir::Operation &node)
+void ConstantLoweringPass::callback(const ir::OperationIndex &node_index, ir::IOperation &node)
{
const auto op_lower_info = _lowered_graph.lower_info().operation.getRawPtr(node_index);
const auto backend = op_lower_info->backend();
@@ -37,7 +37,7 @@ void ConstantLoweringPass::callback(const ir::OperationIndex &node_index, ir::Op
const auto factor = PermuteFactor{backend, layout};
// Now this runtime does not support the node making output of operation as constant
- for (const auto input : node.getInputs() | ir::Remove::DUPLICATED | ir::Remove::UNDEFINED)
+ for (const auto &input : node.getInputs() | ir::Remove::DUPLICATED | ir::Remove::UNDEFINED)
{
auto &object = _graph.operands().at(input);
if (object.isConstant())
diff --git a/runtime/onert/core/src/compiler/pass/ConstantLoweringPass.h b/runtime/onert/core/src/compiler/pass/ConstantLoweringPass.h
index e17d776d1..d60a1033f 100644
--- a/runtime/onert/core/src/compiler/pass/ConstantLoweringPass.h
+++ b/runtime/onert/core/src/compiler/pass/ConstantLoweringPass.h
@@ -36,7 +36,7 @@ public:
std::string id() final { return "ConstantLoweringPass"; }
public:
- void callback(const ir::OperationIndex &index, ir::Operation &node) final;
+ void callback(const ir::OperationIndex &index, ir::IOperation &node) final;
};
} // namespace pass
diff --git a/runtime/onert/core/src/compiler/pass/ConstantOutputPass.cc b/runtime/onert/core/src/compiler/pass/ConstantOutputPass.cc
index c176f6ffb..1448de473 100644
--- a/runtime/onert/core/src/compiler/pass/ConstantOutputPass.cc
+++ b/runtime/onert/core/src/compiler/pass/ConstantOutputPass.cc
@@ -49,7 +49,7 @@ void ConstantOutputPass::callback(const ir::OperandIndex &ind, ir::Operand &obj)
// Make the operations that uses this operand to use the generated operand
auto orig_uses = obj.getUses();
- for (auto use : orig_uses)
+ for (auto &&use : orig_uses)
{
permute_input_obj.insertUse(use);
obj.removeUse(use);
diff --git a/runtime/onert/core/src/compiler/pass/IPass.h b/runtime/onert/core/src/compiler/pass/IPass.h
new file mode 100644
index 000000000..77f5916fd
--- /dev/null
+++ b/runtime/onert/core/src/compiler/pass/IPass.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_COMPILER_PASS_IPASS_H__
+#define __ONERT_COMPILER_PASS_IPASS_H__
+
+#include <string>
+
+namespace onert
+{
+namespace compiler
+{
+namespace pass
+{
+
+struct IPass
+{
+ virtual ~IPass() = default;
+
+ virtual std::string id() = 0;
+ virtual void run() = 0;
+};
+
+} // namespace pass
+} // namespace compiler
+} // namespace onert
+
+#endif // __ONERT_COMPILER_PASS_IPASS_H__
diff --git a/runtime/onert/core/src/compiler/pass/LoweredOperandPass.h b/runtime/onert/core/src/compiler/pass/LoweredOperandPass.h
index 1f1f32f6d..64831a0ac 100644
--- a/runtime/onert/core/src/compiler/pass/LoweredOperandPass.h
+++ b/runtime/onert/core/src/compiler/pass/LoweredOperandPass.h
@@ -18,7 +18,7 @@
#define __ONERT_IR_PASS_LOWERED_OPERAND_PASS_H__
#include "OperandPass.h"
-#include "compiler/LoweredGraph.h"
+#include "compiler/ILoweredGraph.h"
namespace onert
{
@@ -30,7 +30,7 @@ namespace pass
class LoweredOperandPass : public OperandPass
{
public:
- LoweredOperandPass(compiler::LoweredGraph &lowered_graph)
+ LoweredOperandPass(compiler::ILoweredGraph &lowered_graph)
: OperandPass{lowered_graph.graph()}, _lowered_graph{lowered_graph}
{
// DO NOTHING
@@ -42,7 +42,7 @@ public:
void callback(const ir::OperandIndex &i, ir::Operand &o) override = 0;
protected:
- compiler::LoweredGraph &_lowered_graph;
+ compiler::ILoweredGraph &_lowered_graph;
};
} // namespace pass
diff --git a/runtime/onert/core/src/compiler/pass/LoweredOperationPass.h b/runtime/onert/core/src/compiler/pass/LoweredOperationPass.h
index 76ee3d7ff..27ca77c91 100644
--- a/runtime/onert/core/src/compiler/pass/LoweredOperationPass.h
+++ b/runtime/onert/core/src/compiler/pass/LoweredOperationPass.h
@@ -18,7 +18,7 @@
#define __ONERT_IR_PASS_LOWERED_OPERATION_PASS_H__
#include "OperationPass.h"
-#include "compiler/LoweredGraph.h"
+#include "compiler/ILoweredGraph.h"
namespace onert
{
@@ -30,7 +30,7 @@ namespace pass
class LoweredOperationPass : public OperationPass
{
public:
- LoweredOperationPass(LoweredGraph &lowered_graph)
+ LoweredOperationPass(ILoweredGraph &lowered_graph)
: OperationPass{lowered_graph.graph()}, _lowered_graph{lowered_graph}
{
// DO NOTHING
@@ -39,10 +39,10 @@ public:
virtual ~LoweredOperationPass() = default;
std::string id() override = 0;
- void callback(const ir::OperationIndex &i, ir::Operation &o) override = 0;
+ void callback(const ir::OperationIndex &i, ir::IOperation &o) override = 0;
protected:
- LoweredGraph &_lowered_graph;
+ ILoweredGraph &_lowered_graph;
};
} // namespace pass
diff --git a/runtime/onert/core/src/compiler/pass/OperationPass.cc b/runtime/onert/core/src/compiler/pass/OperationPass.cc
index 357a8798a..bd9bcb4a4 100644
--- a/runtime/onert/core/src/compiler/pass/OperationPass.cc
+++ b/runtime/onert/core/src/compiler/pass/OperationPass.cc
@@ -17,7 +17,7 @@
#include "OperationPass.h"
#include "ir/Index.h"
-#include "ir/Operation.h"
+#include "ir/IOperation.h"
#include "ir/Graph.h"
namespace onert
@@ -30,7 +30,7 @@ namespace pass
void OperationPass::run()
{
_graph.operations().iterate(
- [&](const ir::OperationIndex &index, ir::Operation &node) { callback(index, node); });
+ [&](const ir::OperationIndex &index, ir::IOperation &node) { callback(index, node); });
}
} // namespace pass
diff --git a/runtime/onert/core/src/compiler/pass/OperationPass.h b/runtime/onert/core/src/compiler/pass/OperationPass.h
index ac4d818a2..0a00b11d1 100644
--- a/runtime/onert/core/src/compiler/pass/OperationPass.h
+++ b/runtime/onert/core/src/compiler/pass/OperationPass.h
@@ -29,7 +29,7 @@ namespace onert
{
namespace ir
{
-class Operation;
+struct IOperation;
} // namespace ir
} // namespace onert
@@ -62,7 +62,7 @@ public:
* @param index is the index of a node in graph
* @param node is the node in graph
*/
- virtual void callback(const ir::OperationIndex &index, ir::Operation &node) = 0;
+ virtual void callback(const ir::OperationIndex &index, ir::IOperation &node) = 0;
/**
* @brief Run the pass
diff --git a/runtime/onert/core/src/compiler/pass/Pass.h b/runtime/onert/core/src/compiler/pass/Pass.h
index 3016df490..b34695c97 100644
--- a/runtime/onert/core/src/compiler/pass/Pass.h
+++ b/runtime/onert/core/src/compiler/pass/Pass.h
@@ -17,6 +17,8 @@
#ifndef __ONERT_COMPILER_PASS_PASS_H__
#define __ONERT_COMPILER_PASS_PASS_H__
+#include "IPass.h"
+
#include <string>
namespace onert
@@ -34,7 +36,7 @@ namespace compiler
namespace pass
{
-class Pass
+class Pass : public IPass
{
public:
Pass(ir::Graph &graph) : _graph{graph} {}
diff --git a/runtime/onert/core/src/compiler/pass/PassRunner.cc b/runtime/onert/core/src/compiler/pass/PassRunner.cc
index 2d11be201..cd1b82bb2 100644
--- a/runtime/onert/core/src/compiler/pass/PassRunner.cc
+++ b/runtime/onert/core/src/compiler/pass/PassRunner.cc
@@ -23,7 +23,7 @@ namespace compiler
namespace pass
{
-PassRunner &PassRunner::append(std::unique_ptr<Pass> pass)
+PassRunner &PassRunner::append(std::unique_ptr<IPass> pass)
{
_passes.emplace_back(std::move(pass));
return *this;
diff --git a/runtime/onert/core/src/compiler/pass/PassRunner.h b/runtime/onert/core/src/compiler/pass/PassRunner.h
index a43c83f89..03bfbe220 100644
--- a/runtime/onert/core/src/compiler/pass/PassRunner.h
+++ b/runtime/onert/core/src/compiler/pass/PassRunner.h
@@ -21,7 +21,7 @@
#include <memory>
#include <vector>
-#include "Pass.h"
+#include "IPass.h"
#include "util/logging.h"
namespace onert
@@ -38,12 +38,12 @@ class PassRunner
{
public:
PassRunner() = default;
- PassRunner &append(std::unique_ptr<Pass> pass);
+ PassRunner &append(std::unique_ptr<IPass> pass);
void run();
private:
- std::vector<std::unique_ptr<Pass>> _passes;
+ std::vector<std::unique_ptr<IPass>> _passes;
};
} // namespace pass
diff --git a/runtime/onert/core/src/compiler/pass/PermutationEliminationPass.cc b/runtime/onert/core/src/compiler/pass/PermutationEliminationPass.cc
index c27ce3d09..d9452c7f9 100644
--- a/runtime/onert/core/src/compiler/pass/PermutationEliminationPass.cc
+++ b/runtime/onert/core/src/compiler/pass/PermutationEliminationPass.cc
@@ -16,6 +16,7 @@
#include "PermutationEliminationPass.h"
+#include "backend/Backend.h"
#include "util/logging.h"
namespace onert
@@ -25,7 +26,7 @@ namespace compiler
namespace pass
{
-void PermutationEliminationPass::callback(const ir::OperationIndex &ind, ir::Operation &node)
+void PermutationEliminationPass::callback(const ir::OperationIndex &ind, ir::IOperation &node)
{
_op_ind = ind;
node.accept(*this);
@@ -73,7 +74,7 @@ void PermutationEliminationPass::visit(const ir::operation::Permute &node)
auto &out_operand_obj = _graph.operands().at(out_operand);
assert(out_operand_obj.getDef() == _op_ind);
out_operand_obj.unsetDef();
- _graph.operations().iterate([&](const ir::OperationIndex &op_ind, ir::Operation &op) {
+ _graph.operations().iterate([&](const ir::OperationIndex &op_ind, ir::IOperation &op) {
if (!op.getOutputs().contains(in_operand))
return;
// Update Operation and Operand edges
@@ -87,7 +88,7 @@ void PermutationEliminationPass::visit(const ir::operation::Permute &node)
_graph.operations().remove(_op_ind);
}
- _graph.operations().iterate([&](const ir::OperationIndex &op_ind, ir::Operation &op) {
+ _graph.operations().iterate([&](const ir::OperationIndex &op_ind, ir::IOperation &op) {
if (!op.getInputs().contains(in_operand))
return;
op.replaceInputs(in_operand, out_operand);
@@ -106,7 +107,7 @@ void PermutationEliminationPass::visit(const ir::operation::Permute &node)
in_operand_obj.removeUse(_op_ind);
// Make operations(that use the output) use the input
- _graph.operations().iterate([&](const ir::OperationIndex &op_ind, ir::Operation &op) {
+ _graph.operations().iterate([&](const ir::OperationIndex &op_ind, ir::IOperation &op) {
if (!op.getInputs().contains(out_operand))
return;
op.replaceInputs(out_operand, in_operand);
diff --git a/runtime/onert/core/src/compiler/pass/PermutationEliminationPass.h b/runtime/onert/core/src/compiler/pass/PermutationEliminationPass.h
index 50c38c53f..18ba99804 100644
--- a/runtime/onert/core/src/compiler/pass/PermutationEliminationPass.h
+++ b/runtime/onert/core/src/compiler/pass/PermutationEliminationPass.h
@@ -49,7 +49,7 @@ public:
std::string id() final { return "PermutationEliminationPass"; }
public:
- void callback(const ir::OperationIndex &i, ir::Operation &n) final;
+ void callback(const ir::OperationIndex &i, ir::IOperation &n) final;
private:
void visit(const ir::operation::Permute &) final;
diff --git a/runtime/onert/core/src/compiler/pass/PermutationInsertionPass.cc b/runtime/onert/core/src/compiler/pass/PermutationInsertionPass.cc
index 0da1e54df..39eb803f5 100644
--- a/runtime/onert/core/src/compiler/pass/PermutationInsertionPass.cc
+++ b/runtime/onert/core/src/compiler/pass/PermutationInsertionPass.cc
@@ -54,13 +54,13 @@ void PermutationInsertionPass::callback(const ir::OperandIndex &index, ir::Opera
std::unordered_map<PermuteFactor, ir::OperandIndex> factor_to_index;
{
assert(operand_li->def_factors().size() == 1);
- for (auto factor : operand_li->def_factors())
+ for (auto &&factor : operand_li->def_factors())
{
factor_to_index.emplace(factor, index);
}
auto insert_set = operand_li->use_factors() - operand_li->def_factors();
- for (auto factor : insert_set)
+ for (auto &&factor : insert_set)
{
const auto permute_operation_index = insertPermute(index, factor);
permute_indexes.push_back(permute_operation_index);
@@ -75,7 +75,7 @@ void PermutationInsertionPass::callback(const ir::OperandIndex &index, ir::Opera
std::list<ir::OperationIndex> remove_list;
auto uses = object.getUses();
- for (auto use : uses)
+ for (auto &&use : uses)
{
// If permute operation, ignore it
if (std::find(permute_indexes.begin(), permute_indexes.end(), use) != permute_indexes.end())
diff --git a/runtime/onert/core/src/compiler/pass/PermutationOperationPass.cc b/runtime/onert/core/src/compiler/pass/PermutationOperationPass.cc
index f83b1ba31..f014d29d3 100644
--- a/runtime/onert/core/src/compiler/pass/PermutationOperationPass.cc
+++ b/runtime/onert/core/src/compiler/pass/PermutationOperationPass.cc
@@ -30,7 +30,7 @@ namespace pass
using namespace ir;
-void PermutationOperationPass::callback(const OperationIndex &, Operation &node)
+void PermutationOperationPass::callback(const OperationIndex &, IOperation &node)
{
node.accept(*this);
}
diff --git a/runtime/onert/core/src/compiler/pass/PermutationOperationPass.h b/runtime/onert/core/src/compiler/pass/PermutationOperationPass.h
index cea5de288..e253a77ad 100644
--- a/runtime/onert/core/src/compiler/pass/PermutationOperationPass.h
+++ b/runtime/onert/core/src/compiler/pass/PermutationOperationPass.h
@@ -36,7 +36,7 @@ public:
std::string id() final { return "PermutationOperationPass"; }
public:
- void callback(const ir::OperationIndex &i, ir::Operation &n) final;
+ void callback(const ir::OperationIndex &i, ir::IOperation &n) final;
public:
void visit(const ir::operation::BinaryArithmetic &) final;
diff --git a/runtime/onert/core/src/compiler/pass/UnusedOperandEliminationPass.cc b/runtime/onert/core/src/compiler/pass/UnusedOperandEliminationPass.cc
index 35fb575b0..162c4e7ef 100644
--- a/runtime/onert/core/src/compiler/pass/UnusedOperandEliminationPass.cc
+++ b/runtime/onert/core/src/compiler/pass/UnusedOperandEliminationPass.cc
@@ -37,15 +37,15 @@ void UnusedOperandEliminationPass::run()
{
util::Set<ir::OperandIndex> used;
- _graph.operations().iterate([&](const ir::OperationIndex &, const ir::Operation &node) {
- for (auto ind : (node.getInputs() + node.getOutputs()) | ir::Remove::UNDEFINED)
+ _graph.operations().iterate([&](const ir::OperationIndex &, const ir::IOperation &node) {
+ for (auto &&ind : (node.getInputs() + node.getOutputs()) | ir::Remove::UNDEFINED)
{
used.add(ind);
}
});
// Graph's inputs/outputs are always considered as used
- for (auto ind : (_graph.getInputs() + _graph.getOutputs()) | ir::Remove::UNDEFINED)
+ for (auto &&ind : (_graph.getInputs() + _graph.getOutputs()) | ir::Remove::UNDEFINED)
{
used.add(ind);
}
diff --git a/runtime/onert/core/src/compiler/train/LoweredTrainableGraph.cc b/runtime/onert/core/src/compiler/train/LoweredTrainableGraph.cc
new file mode 100644
index 000000000..490c648cd
--- /dev/null
+++ b/runtime/onert/core/src/compiler/train/LoweredTrainableGraph.cc
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "compiler/train/LoweredTrainableGraph.h"
+
+#include "../ManualScheduler.h"
+#include "../pass/ConstantInsertionPass.h"
+#include "../pass/ConstantLoweringPass.h"
+#include "../pass/PassRunner.h"
+#include "../pass/PermutationEliminationPass.h"
+#include "../pass/PermutationInsertionPass.h"
+#include "../pass/PermutationOperationPass.h"
+#include "../../backend/builtin/Config.h"
+#include "../../dumper/text/GraphDumper.h"
+#include "../../ir/verifier/Verifier.h"
+#include "TrainableOperationConverter.h"
+
+#include "backend/Backend.h"
+#include "backend/train/ITrainableBackend.h"
+#include "compiler/BackendResolver.h"
+#include "util/logging.h"
+
+#include <cassert>
+#include <sstream>
+
+namespace onert
+{
+namespace compiler
+{
+namespace train
+{
+
+LoweredTrainableGraph::LoweredTrainableGraph(ir::train::TrainableGraph &graph,
+ const CompilerOptions &options)
+ : _trainable_graph{graph}
+{
+ lowerGraph(options);
+}
+
+void LoweredTrainableGraph::lowerGraph(const CompilerOptions &options)
+{
+ // Build backend contexts
+ auto &backend_manager = BackendManager::get();
+ // Create contexts for other backends
+ for (auto &&backend_str : options.backend_list)
+ {
+ backend_manager.loadBackend(backend_str);
+ auto backend = backend_manager.get(backend_str);
+
+ // TODO As the default value of backend list contains "cpu", "acl_cl" and "acl_neon", and some
+ // are not available on x64 or some other platforms. So this may be a workaround for x64 and
+ // we should change it back(throw if backend is not loaded) later.
+ if (!backend)
+ {
+ VERBOSE(LoweredTrainableGraph) << "Cannot load backend - " << backend_str << std::endl;
+ continue;
+ }
+ }
+ if (backend_manager.num_backends() == 0)
+ throw std::runtime_error{"No available backends loaded."};
+
+ // TODO Move "schedule" phase out of here
+ // TODO Scheduling
+ std::unique_ptr<BackendResolver> backend_resolver;
+ auto all_backends = backend_manager.getAll();
+
+ auto scheduler = ManualScheduler(all_backends, options);
+ backend_resolver = scheduler.schedule(_trainable_graph.graph());
+
+ // Check if backends are trainable
+ _trainable_graph.operations().iterate(
+ [&](const ir::OperationIndex &op_ind, const ir::IOperation &) {
+ const auto backend = backend_resolver->getBackend(op_ind);
+
+ // TODO Remove dynamic_cast
+ if (dynamic_cast<const backend::train::ITrainableBackend *>(backend) == nullptr)
+ {
+ throw std::runtime_error(backend->config()->id() + "backend does not support training");
+ }
+ });
+
+ makeLowerInfo(*backend_resolver);
+ VERBOSE(LoweredTrainableGraph) << "dump before mandatory passes" << std::endl;
+ dumper::text::dumpLoweredGraph(*this);
+
+ // Mandatory passes - kind of legalization(?)
+ compiler::pass::PassRunner{}
+ .append(std::make_unique<compiler::pass::ConstantInsertionPass>(*this))
+ .append(std::make_unique<compiler::pass::ConstantLoweringPass>(*this))
+ .append(std::make_unique<compiler::pass::PermutationOperationPass>(*this))
+ .append(std::make_unique<compiler::pass::PermutationInsertionPass>(*this))
+ .run();
+
+ // TODO Move converting Permute op into PermutationInsertionPass
+ auto op_converter = TrainableOperationConverter{_trainable_graph, nullptr};
+ _trainable_graph.operations().iterate(
+ [&](const onert::ir::OperationIndex &index, const onert::ir::IOperation &op) {
+ if (op.opcode() == ir::OpCode::Permute)
+ {
+ auto trainable_op = op_converter(op);
+ auto gen_index = _trainable_graph.replaceOperation(index, std::move(trainable_op));
+ UNUSED_RELEASE(gen_index);
+ assert(gen_index == index);
+ }
+ });
+
+ dumpLowerInfo();
+
+ // Optimization passes (optional)
+ compiler::pass::PassRunner{}
+ .append(std::make_unique<compiler::pass::PermutationEliminationPass>(*this))
+ .run();
+
+ // TODO Update LowerInfo for training
+
+ VERBOSE(LoweredTrainableGraph) << "Dump after all the passes" << std::endl;
+ for (auto &&operand : _trainable_graph.getInputs())
+ VERBOSE(LoweredTrainableGraph) << "Graph Input : " << operand << std::endl;
+ for (auto &&operand : _trainable_graph.getOutputs())
+ VERBOSE(LoweredTrainableGraph) << "Graph Output : " << operand << std::endl;
+ dumper::text::dumpLoweredGraph(*this);
+
+ // Graph verifications
+ {
+ assert(ir::verifier::InputOutputChecker().verify(_trainable_graph.graph()));
+ assert(ir::verifier::DAGChecker().verify(_trainable_graph.graph()));
+ assert(ir::verifier::EdgeChecker().verify(_trainable_graph.graph()));
+ }
+}
+
+void LoweredTrainableGraph::makeLowerInfo(const compiler::BackendResolver &backend_resolver)
+{
+ _trainable_graph.operands().iterate([&](const ir::OperandIndex &index, const ir::Operand &) {
+ lower_info().operand.set(index, std::make_unique<OperandLowerInfo>());
+ });
+
+ // Set operand lower info using assigned backends to operations
+ _trainable_graph.operations().iterate(
+ [&](const ir::OperationIndex &op_ind, const ir::IOperation &op) {
+ auto backend = backend_resolver.getBackend(op_ind);
+ if (!backend)
+ {
+ throw std::runtime_error{"Fail to find backend for " + op.name() + " operation"};
+ }
+
+ auto frontend_layout = _trainable_graph.layout();
+
+ // The layout of each backend should be set at another place
+ // TODO Change setting layout of each backend at another place
+ auto backend_layout = backend->config()->supportLayout(op, frontend_layout);
+
+ for (auto &&ind : op.getInputs() | ir::Remove::UNDEFINED)
+ {
+ auto &operand_li = lower_info().operand.at(ind);
+ operand_li.addUsePermuteFactor(PermuteFactor{backend, backend_layout});
+ }
+ for (auto &&ind : op.getOutputs() | ir::Remove::UNDEFINED)
+ {
+ auto &operand_li = lower_info().operand.at(ind);
+ operand_li.addDefPermuteFactor(PermuteFactor{backend, backend_layout});
+ }
+ lower_info().operation.set(
+ op_ind, std::make_unique<compiler::OperationLowerInfo>(backend, backend_layout));
+ });
+
+ // Handle graph inputs and outputs
+ const auto builtin_backend = BackendManager::get().getBuiltin();
+ auto factor = PermuteFactor{builtin_backend, _trainable_graph.layout()};
+ for (auto &&index : _trainable_graph.getInputs() | ir::Remove::UNDEFINED)
+ {
+ auto &operand_li = lower_info().operand.at(index);
+ assert(operand_li.def_factors().empty());
+ operand_li.addDefPermuteFactor(factor);
+ }
+ for (auto &&index : _trainable_graph.getOutputs() | ir::Remove::UNDEFINED)
+ {
+ auto &operand_li = lower_info().operand.at(index);
+ operand_li.addUsePermuteFactor(factor);
+ }
+
+ // Handle variable tensors
+ _trainable_graph.operands().iterate([&](const ir::OperandIndex &index, ir::Operand &operand) {
+ // Some inputs of an operation could be non-constant, but not existed in graph inputs/outputs
+ // and not undefined operand - these are variable tensors. For example,
+ // UnidirectionalSequenceLSTM has such inputs.
+ if (operand.info().isVariable())
+ {
+ // The variable operand with buffer is not supported yet
+ assert(operand.data() == nullptr);
+ assert(operand.getUses().size() == 1 && !operand.getDef().valid());
+ auto operand_li = lower_info().operand.at(index);
+ assert(operand_li.def_factors().empty());
+ operand_li.addDefPermuteFactor(operand_li.use_factors().getOnlyElement());
+ }
+ });
+}
+
+void LoweredTrainableGraph::dumpLowerInfo()
+{
+ if (::onert::util::logging::ctx.enabled() == false)
+ return;
+
+ std::map<uint32_t, std::string> dumps;
+
+ _trainable_graph.operands().iterate([&](const ir::OperandIndex &index, ir::Operand &object) {
+ const auto operand_lower_info = lower_info().operand.getRawPtr(index);
+ assert(operand_lower_info);
+ if (!operand_lower_info->def_factors().empty() || !operand_lower_info->use_factors().empty())
+ {
+ auto shape_to_string = [](const ir::Shape &shape) {
+ std::stringstream sstream;
+ sstream << "{ ";
+ for (auto i = 0; i < shape.rank(); ++i)
+ sstream << (shape.dim(i)) << " ";
+ sstream << "}";
+ return sstream.str();
+ };
+
+ auto factors_to_string = [](const PermuteFactorSet &factors) {
+ std::string str;
+ for (auto &&factor : factors)
+ {
+ str += factor.backend()->config()->id();
+ str += "(" + to_string(factor.layout()) + ")";
+ str += " ";
+ }
+ return "{ " + str + "}";
+ };
+
+ auto operation_index_set_to_string = [](const ir::OperationIndexSet &operations) {
+ std::stringstream sstream;
+ sstream << "{ ";
+ for (auto &&op : operations)
+ sstream << op << " ";
+ sstream << "}";
+ return sstream.str();
+ };
+
+ auto data_to_str = [](const ir::Data *data) {
+ return (data ? (std::to_string(data->size()) + " bytes") : "N/A");
+ };
+
+ std::string shape_str = shape_to_string(object.shape());
+ std::string def_op = operation_index_set_to_string({object.getDef()});
+ std::string use_ops = operation_index_set_to_string(object.getUses());
+ std::string def_factors = factors_to_string(operand_lower_info->def_factors());
+ std::string use_factors = factors_to_string(operand_lower_info->use_factors());
+ std::stringstream sstream;
+ sstream << "Operand " << index << " Info" << std::endl;
+ sstream << " - Shape : " << shape_str << std::endl;
+ sstream << " - Def/Uses : Def " << def_op << " Uses " << use_ops << std::endl;
+ sstream << " - Data : " << data_to_str(object.data()) << std::endl;
+ sstream << " - LowerInfo : Def " << def_factors << " Uses " << use_factors << std::endl;
+ dumps.emplace(index.value(), sstream.str());
+ }
+ });
+
+ for (const auto &e : dumps)
+ {
+ if (!e.second.empty())
+ {
+ std::istringstream iss(e.second);
+ std::string line;
+ while (std::getline(iss, line))
+ VERBOSE(Lower) << line << std::endl;
+ }
+ }
+}
+
+} // namespace train
+} // namespace compiler
+} // namespace onert
diff --git a/runtime/onert/core/src/compiler/train/StaticDerivativeShapeInferer.cc b/runtime/onert/core/src/compiler/train/StaticDerivativeShapeInferer.cc
new file mode 100644
index 000000000..d2153296f
--- /dev/null
+++ b/runtime/onert/core/src/compiler/train/StaticDerivativeShapeInferer.cc
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "StaticDerivativeShapeInferer.h"
+#include "util/ShapeInference.h"
+#include "util/logging.h"
+
+#include <misc/polymorphic_downcast.h>
+
+#include <sstream>
+#include <stdexcept>
+
+namespace onert
+{
+namespace compiler
+{
+namespace train
+{
+
+void StaticDerivativeShapeInferer::infer()
+{
+ // It is not determined to iterate in reverse order.
+ auto sorted_ops = _lowered_subg->graph().topolSortOperations();
+ for (auto it = sorted_ops.rbegin(); it != sorted_ops.rend(); ++it)
+ {
+ const auto op_idx = *it;
+ const auto &op = _lowered_subg->trainable_graph().operation(op_idx);
+ if (checkDynamicInput(op))
+ {
+ std::stringstream msg;
+ msg << "StaticDerivativeShapeInferer does not support dynamic shape yet, ";
+ msg << op.name() << "(op index: " << op_idx << ") has dynamic shape.";
+ throw std::runtime_error(msg.str());
+ }
+
+ checkOutput(op);
+
+ op.accept(*this);
+ }
+}
+
+void StaticDerivativeShapeInferer::dump()
+{
+ // TODO dump
+}
+
+bool StaticDerivativeShapeInferer::checkDynamicInput(const ir::IOperation &op)
+{
+ const auto &operands = _lowered_subg->graph().operands();
+ for (auto input_idx : op.getInputs() | ir::Remove::UNDEFINED | ir::Remove::DUPLICATED)
+ {
+ if (operands.at(input_idx).info().isDynamic())
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void StaticDerivativeShapeInferer::checkOutput(const ir::IOperation &op)
+{
+ const auto &derivatives = _lowered_subg->trainable_graph().derivatives();
+ for (auto output_idx : op.getOutputs() | ir::Remove::UNDEFINED | ir::Remove::DUPLICATED)
+ {
+ if (!derivatives.exist(output_idx))
+ {
+ std::stringstream msg;
+ msg << "StaticDerivativeShapeInferer : Invalid output, ";
+ msg << op.name() << "'s derivative output(index: " << output_idx << ") does not exist.";
+ throw std::runtime_error(msg.str());
+ }
+ }
+}
+
+void StaticDerivativeShapeInferer::setShape(const ir::OperandIndex &index, const ir::Shape &shape)
+{
+ auto &tgraph = _lowered_subg->trainable_graph();
+
+ if (tgraph.derivatives().exist(index))
+ tgraph.changeDerivativeShape(index, shape);
+ else
+ {
+ // NOTE This code assumes the types are always the same, but I'm not sure.
+ const auto &type = tgraph.operands().at(index).typeInfo();
+ const auto new_index = tgraph.addDerivative(index, std::make_unique<ir::Operand>(shape, type));
+ assert(new_index == index);
+ UNUSED_RELEASE(new_index);
+ }
+}
+
+void StaticDerivativeShapeInferer::visit(const ir::train::operation::Conv2D &)
+{
+ // NYI
+}
+
+void StaticDerivativeShapeInferer::visit(const ir::train::operation::ElementwiseActivation &)
+{
+ // NYI
+}
+
+void StaticDerivativeShapeInferer::visit(const ir::train::operation::Loss &)
+{
+ // NYI
+}
+
+void StaticDerivativeShapeInferer::visit(const ir::train::operation::Permute &op)
+{
+ const auto &derivatives = _lowered_subg->trainable_graph().derivatives();
+
+ const auto &output_idx = op.getOutputs().at(0);
+ const auto &output = derivatives.at(output_idx);
+
+ // re-sizing input derivative shape
+ const auto &input_idx = op.getInputs().at(0);
+ const auto &new_shape = output.info().shape();
+ setShape(input_idx, new_shape);
+}
+
+void StaticDerivativeShapeInferer::visit(const ir::train::operation::Pool2D &)
+{
+ // NYI
+}
+
+void StaticDerivativeShapeInferer::visit(const ir::train::operation::Reshape &)
+{
+ // NYI
+}
+
+void StaticDerivativeShapeInferer::visit(const ir::train::operation::Softmax &)
+{
+ // NYI
+}
+
+} // namespace train
+} // namespace compiler
+} // namespace onert
diff --git a/runtime/onert/core/src/compiler/train/StaticDerivativeShapeInferer.h b/runtime/onert/core/src/compiler/train/StaticDerivativeShapeInferer.h
new file mode 100644
index 000000000..48b3172d2
--- /dev/null
+++ b/runtime/onert/core/src/compiler/train/StaticDerivativeShapeInferer.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_COMPILER_STATIC_DERIVATIVE_SHAPE_INFERER_H__
+#define __ONERT_COMPILER_STATIC_DERIVATIVE_SHAPE_INFERER_H__
+
+#include "ir/train/TrainableOperationVisitor.h"
+
+#include "compiler/train/LoweredTrainableGraph.h"
+#include "ir/Index.h"
+
+#include <memory>
+#include <unordered_map>
+
+namespace onert
+{
+namespace compiler
+{
+namespace train
+{
+
+/**
+ * @brief Class to infer shape before running kernels. It does the following:
+ * - re-calculate and set output shape at compile time (before running kernels)
+ * - if calculation cannot be done at compile time, mark the outputs to be dynamic, meaning
+ * shapes of outputs will be calculated during running kernels
+ */
+class StaticDerivativeShapeInferer : public ir::train::TrainableOperationVisitor
+{
+public:
+ StaticDerivativeShapeInferer(compiler::train::LoweredTrainableGraph *lowered_subg)
+ : _lowered_subg{lowered_subg}
+ {
+ }
+
+ /**
+ * @brief Infer shape of operands belonging to ops and set the output shape.
+ * If output shape cannot be known without running op, mark it so that it can be allocated
+ * when running kernel.
+ */
+ void infer(void);
+
+ void dump();
+
+private:
+ bool checkDynamicInput(const ir::IOperation &op);
+ void checkOutput(const ir::IOperation &op);
+ void setShape(const ir::OperandIndex &index, const ir::Shape &shape);
+
+private:
+ void visit(const ir::train::operation::Conv2D &op) override;
+ void visit(const ir::train::operation::ElementwiseActivation &op) override;
+ void visit(const ir::train::operation::Loss &op) override;
+ void visit(const ir::train::operation::Permute &op) override;
+ void visit(const ir::train::operation::Pool2D &op) override;
+ void visit(const ir::train::operation::Reshape &op) override;
+ void visit(const ir::train::operation::Softmax &op) override;
+
+private:
+ compiler::train::LoweredTrainableGraph *_lowered_subg;
+};
+
+} // namespace train
+} // namespace compiler
+} // namespace onert
+
+#endif // __ONERT_COMPILER_STATIC_DERIVATIVE_SHAPE_INFERER_H__
diff --git a/runtime/onert/core/src/compiler/train/TensorRegistries.h b/runtime/onert/core/src/compiler/train/TensorRegistries.h
new file mode 100644
index 000000000..48eaf10a1
--- /dev/null
+++ b/runtime/onert/core/src/compiler/train/TensorRegistries.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_COMPILER_TRAIN_TENSOR_REGISTRIES_H__
+#define __ONERT_COMPILER_TRAIN_TENSOR_REGISTRIES_H__
+
+#include "../../backend/builtin/Config.h"
+#include "../../backend/builtin/train/TensorRegistry.h"
+
+#include <backend/train/TrainableBackendContext.h>
+
+#include <memory>
+#include <unordered_set>
+
+namespace onert
+{
+namespace compiler
+{
+namespace train
+{
+
+class TensorRegistries
+{
+public:
+ TensorRegistries() = default;
+
+ TensorRegistries(const backend::train::TrainableBackendContexts &backend_contexts,
+ bool include_builtin)
+ {
+ for (const auto &e : backend_contexts)
+ {
+ auto tensor_reg = e.second->tensor_registry();
+ if (e.first->config()->id() == backend::builtin::Config::ID)
+ {
+ _builtin_tensor_reg =
+ std::dynamic_pointer_cast<backend::builtin::train::TensorRegistry>(tensor_reg);
+ if (include_builtin)
+ _tensor_regs.insert(tensor_reg);
+ }
+ else
+ {
+ _tensor_regs.insert(tensor_reg);
+ }
+ }
+ }
+
+ std::unordered_set<std::shared_ptr<backend::train::ITensorRegistry>>::const_iterator begin() const
+ {
+ return _tensor_regs.cbegin();
+ }
+ std::unordered_set<std::shared_ptr<backend::train::ITensorRegistry>>::const_iterator end() const
+ {
+ return _tensor_regs.cend();
+ }
+
+ std::shared_ptr<backend::builtin::train::TensorRegistry> getBuiltinTensorRegistry() const
+ {
+ return _builtin_tensor_reg;
+ }
+
+ backend::ITensor *getITensor(ir::OperandIndex index) const
+ {
+ for (auto &&tensor_reg : _tensor_regs)
+ {
+ auto tensor = tensor_reg->getITensor(index);
+ if (tensor)
+ return tensor;
+ }
+ return nullptr;
+ }
+
+ backend::ITensor *getDerivativeITensor(ir::OperandIndex index) const
+ {
+ for (auto &&tensor_reg : _tensor_regs)
+ {
+ auto tensor = tensor_reg->getDerivativeITensor(index);
+ if (tensor)
+ return tensor;
+ }
+ return nullptr;
+ }
+
+private:
+ std::unordered_set<std::shared_ptr<backend::train::ITensorRegistry>> _tensor_regs;
+ std::shared_ptr<backend::builtin::train::TensorRegistry> _builtin_tensor_reg;
+};
+
+} // namespace train
+} // namespace compiler
+} // namespace onert
+
+#endif // __ONERT_COMPILER_TRAIN_TENSOR_REGISTRIES_H__
diff --git a/runtime/onert/core/src/compiler/train/TrainableOperationConverter.cc b/runtime/onert/core/src/compiler/train/TrainableOperationConverter.cc
new file mode 100644
index 000000000..d20ae9fd3
--- /dev/null
+++ b/runtime/onert/core/src/compiler/train/TrainableOperationConverter.cc
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TrainableOperationConverter.h"
+
+#include "ir/train/Operations.Include.h"
+#include "util/Utils.h"
+
+namespace onert
+{
+namespace compiler
+{
+namespace train
+{
+
+TrainableOperationConverter::TrainableOperationConverter(
+ ir::train::TrainableGraph &tgraph, const compiler::train::TrainingInfo *training_info)
+ : UntrainableOperationConverter{tgraph}, _training_info{training_info}
+{
+ // Avoid unused-private-field error
+ UNUSED_RELEASE(_training_info);
+}
+
+void TrainableOperationConverter::visit(const ir::operation::Conv2D &node)
+{
+ _return_op = std::make_unique<ir::train::operation::Conv2D>(node);
+}
+
+void TrainableOperationConverter::visit(const ir::operation::ElementwiseActivation &node)
+{
+ if (node.param().op_type == ir::operation::ElementwiseActivation::Type::RELU)
+ {
+ _return_op = std::make_unique<ir::train::operation::ElementwiseActivation>(node);
+ }
+ else
+ {
+ UntrainableOperationConverter::visit(node);
+ }
+}
+
+void TrainableOperationConverter::visit(const ir::operation::FullyConnected &node)
+{
+ _return_op = std::make_unique<ir::train::operation::FullyConnected>(node);
+}
+
+void TrainableOperationConverter::visit(const ir::operation::Loss &node)
+{
+ _return_op = std::make_unique<ir::train::operation::Loss>(node);
+}
+
+void TrainableOperationConverter::visit(const ir::operation::Permute &node)
+{
+ _return_op = std::make_unique<ir::train::operation::Permute>(node);
+}
+
+void TrainableOperationConverter::visit(const ir::operation::Pool2D &node)
+{
+ _return_op = std::make_unique<ir::train::operation::Pool2D>(node);
+}
+
+void TrainableOperationConverter::visit(const ir::operation::Reshape &node)
+{
+ _return_op = std::make_unique<ir::train::operation::Reshape>(node);
+}
+
+void TrainableOperationConverter::visit(const ir::operation::Softmax &node)
+{
+ _return_op = std::make_unique<ir::train::operation::Softmax>(node);
+}
+
+} // namespace train
+} // namespace compiler
+} // namespace onert
diff --git a/runtime/onert/core/src/compiler/train/TrainableOperationConverter.h b/runtime/onert/core/src/compiler/train/TrainableOperationConverter.h
new file mode 100644
index 000000000..5f6fc10c3
--- /dev/null
+++ b/runtime/onert/core/src/compiler/train/TrainableOperationConverter.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_COMPILER_TRAIN_TRAINABLE_OPERATION_CONVERTER_H__
+#define __ONERT_COMPILER_TRAIN_TRAINABLE_OPERATION_CONVERTER_H__
+
+#include "UntrainableOperationConverter.h"
+
+#include "compiler/train/TrainingInfo.h"
+
+namespace onert
+{
+namespace compiler
+{
+namespace train
+{
+
+class TrainableOperationConverter : public UntrainableOperationConverter
+{
+public:
+ TrainableOperationConverter(ir::train::TrainableGraph &trainable_graph,
+ const compiler::train::TrainingInfo *training_info);
+
+ using UntrainableOperationConverter::operator();
+
+private:
+ void visit(const ir::operation::Conv2D &) override;
+ void visit(const ir::operation::ElementwiseActivation &) override;
+ void visit(const ir::operation::FullyConnected &) override;
+ void visit(const ir::operation::Loss &node) override;
+ void visit(const ir::operation::Permute &node) override;
+ void visit(const ir::operation::Pool2D &node) override;
+ void visit(const ir::operation::Reshape &) override;
+ void visit(const ir::operation::Softmax &) override;
+
+private:
+ const compiler::train::TrainingInfo *_training_info;
+};
+
+} // namespace train
+} // namespace compiler
+} // namespace onert
+
+#endif // __ONERT_COMPILER_TRAIN_TRAINABLE_OPERATION_CONVERTER_H__
diff --git a/runtime/onert/core/src/compiler/train/TrainingCompiler.cc b/runtime/onert/core/src/compiler/train/TrainingCompiler.cc
new file mode 100644
index 000000000..711af1651
--- /dev/null
+++ b/runtime/onert/core/src/compiler/train/TrainingCompiler.cc
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TrainingCompiler.h"
+
+#include "StaticDerivativeShapeInferer.h"
+#include "TrainableOperationConverter.h"
+#include "pass/LossInsertionPass.h"
+#include "../CompilerHelpers.h"
+#include "../ExecutorFactory.h"
+#include "../pass/ConstantOutputPass.h"
+#include "../pass/OddOutputPass.h"
+#include "../pass/PassRunner.h"
+#include "../pass/UnusedOperandEliminationPass.h"
+#include "../ShapeValidator.h"
+#include "../../dumper/dot/DotDumper.h"
+#include "../../exec/train/TrainableExecutors.h"
+#include "../../ir/OperationDumper.h"
+#include "../../ir/verifier/Verifier.h"
+
+#include <compiler/StaticShapeInferer.h>
+#include <compiler/train/LoweredTrainableGraph.h>
+#include <ir/train/TrainableGraph.h>
+#include <exec/train/optimizer/SGD.h>
+
+#include <misc/polymorphic_downcast.h>
+#include <misc/string_helpers.h>
+
+namespace onert
+{
+namespace compiler
+{
+namespace train
+{
+
+TrainingCompiler::TrainingCompiler(const std::shared_ptr<ir::NNPkg> &nnpkg,
+ std::vector<std::unique_ptr<CompilerOptions>> &copts,
+ const TrainingInfo &training_info)
+ : _model{nnpkg->primary_model()}, _options{copts[0].get()}, _training_info{training_info}
+{
+ if (nnpkg->model_count() > 1)
+ throw std::runtime_error("TrainingCompiler does not support multiple models yet");
+
+ if (nnpkg->primary_model()->subgraphs_count() > 1)
+ throw std::runtime_error("TrainingCompiler does not support multiple subgraphs yet");
+}
+
+std::shared_ptr<CompilerArtifact> TrainingCompiler::compile(void)
+{
+ /***************************************************
+ * Prepare compilation phase
+ ***************************************************/
+ if (!_options)
+ throw std::runtime_error{"Empty compile option"};
+
+ // Mode check
+ // TODO handle option for each model
+ if (_options->he_profiling_mode)
+ {
+ if (!_options->he_scheduler)
+ throw std::runtime_error("Heterogeneous scheduler must be enabled during profiling.");
+
+ if (_options->executor != "Dataflow")
+ throw std::runtime_error("Profiling mode works only with 'Dataflow' executor");
+ }
+
+ if (!_options->minmax_filepath.empty())
+ {
+ if (_options->executor != "Linear")
+ throw std::runtime_error("Recording minmax works only with Linear executor");
+ }
+
+ _options->forceInternalOptions();
+ _options->verboseOptions();
+
+ auto custom_kernel_builder = _model->getKernelBuilder();
+
+ _model->iterate([&](const ir::SubgraphIndex &, ir::IGraph &graph) {
+ auto &subg = nnfw::misc::polymorphic_downcast<ir::Graph &>(graph);
+ // Mandatory passes
+ compiler::pass::PassRunner{}
+ .append(std::make_unique<compiler::pass::ConstantOutputPass>(subg))
+ .append(std::make_unique<compiler::pass::OddOutputPass>(subg))
+ .run();
+
+ // Optimizations
+ compiler::pass::PassRunner{}
+ .append(std::make_unique<compiler::pass::UnusedOperandEliminationPass>(subg))
+ .run();
+ });
+
+ std::unordered_map<ir::SubgraphIndex, std::shared_ptr<ir::train::TrainableGraph>>
+ trainable_subgraphs;
+
+ if (_model->hasOnly<ir::Graph>())
+ {
+ // Create trainable subgraphs by copy and converting inference model
+ _model->iterate([&](const ir::SubgraphIndex &subg_index, const ir::IGraph &graph) {
+ const auto &subg = nnfw::misc::polymorphic_downcast<const ir::Graph &>(graph);
+ // Create TrainableGraph by copying Graph
+ auto trainable_subg = std::make_shared<ir::train::TrainableGraph>(subg);
+
+ // Convert operations to trainable operations
+ auto converter = TrainableOperationConverter{*trainable_subg, &_training_info};
+ subg.operations().iterate(
+ [&](const onert::ir::OperationIndex &op_index, const onert::ir::IOperation &op) {
+ auto trainable_op = converter(op);
+ auto gen_index = trainable_subg->replaceOperation(op_index, std::move(trainable_op));
+ UNUSED_RELEASE(gen_index);
+ assert(gen_index == op_index);
+ });
+
+ trainable_subgraphs[subg_index] = std::move(trainable_subg);
+ });
+ }
+ else
+ {
+ // TODO Support models that have TrainableGraphs
+ throw std::runtime_error("TrainingCompiler: Invalid model");
+ }
+
+ // operation
+ _model.reset();
+
+ // Apply pass for trainable subgraphs
+ for (auto &&pair : trainable_subgraphs)
+ {
+ auto trainable_subg = pair.second;
+ auto subg_index = pair.first;
+
+ compiler::pass::PassRunner{}
+ .append(std::make_unique<train::pass::LossInsertionPass>(*trainable_subg, &_training_info,
+ subg_index))
+ .run();
+ }
+
+ // Change input shape according to batch_size
+ for (auto &&pair : trainable_subgraphs)
+ {
+ auto trainable_subg = pair.second;
+
+ for (const auto &ind : trainable_subg->getInputs())
+ {
+ auto &input = trainable_subg->operands().at(ind);
+ auto new_shape = input.info().shape();
+ // TODO Consider batch size index
+ if (new_shape.dim(0) != 1)
+ throw std::runtime_error("the first dim is not 1. It is not supported yet.");
+ new_shape.dim(0) = _training_info.batchSize();
+ input.info().shape(new_shape);
+ }
+ }
+
+ /***************************************************
+ * Backend independent analysis & optimization phase
+ ***************************************************/
+ // TODO Handle dump level for each model
+ auto dump_level = static_cast<dumper::dot::DotDumper::Level>(_options->graph_dump_level);
+ onert::dumper::dot::DotDumper dot_dumper(dump_level);
+
+ // Tracing context
+ auto tracing_ctx = std::make_unique<util::TracingCtx>();
+
+ // Lower: Assign backend
+ std::unordered_map<ir::SubgraphIndex, std::unique_ptr<compiler::train::LoweredTrainableGraph>>
+ lowered_subgs;
+ {
+ for (auto &&pair : trainable_subgraphs)
+ {
+ auto &subg_index = pair.first;
+ auto trainable_subg = pair.second;
+
+ // Lower: Assign backend
+ lowered_subgs[subg_index] =
+ std::make_unique<compiler::train::LoweredTrainableGraph>(*trainable_subg, *_options);
+ // Set tracing_ctx for copied graph
+ if (tracing_ctx != nullptr)
+ tracing_ctx->setSubgraphIndex(&(lowered_subgs[subg_index]->graph()), subg_index.value());
+ }
+ }
+
+ for (const auto &pair : lowered_subgs)
+ {
+ const auto &subg_index = pair.first;
+ const auto &lowered_subg = pair.second;
+ dot_dumper.dump(*lowered_subg, nnfw::misc::str("after_lower_subg-", subg_index.value()));
+ }
+
+ // Set derivatives as default tensor info
+ for (const auto &pair : lowered_subgs)
+ {
+ auto lowered_subg = pair.second.get();
+ auto &tgraph = lowered_subg->trainable_graph();
+ tgraph.operands().iterate([&](const ir::OperandIndex &index, const ir::Operand &obj) {
+ if (!obj.isConstant())
+ {
+ auto deriv = std::make_unique<ir::Operand>(obj);
+ const auto gen_index = tgraph.addDerivative(index, std::move(deriv));
+ assert(gen_index == index);
+ UNUSED_RELEASE(gen_index);
+ }
+ });
+ }
+
+ // Shape inference.
+ {
+ // Run the StaticShapeInfer of primary subg. All child StaticShapeInferers are called
+ // recursively
+ std::unordered_map<ir::SubgraphIndex, std::unique_ptr<StaticShapeInferer>> inferers =
+ createStaticShapeInferers(lowered_subgs);
+
+ const auto primary_subg_idx = ir::SubgraphIndex{0};
+ inferers.at(primary_subg_idx)->infer();
+
+ for (const auto &pair_inferer : inferers)
+ {
+ const auto inferer = pair_inferer.second.get();
+ inferer->dump();
+ }
+
+ // NOTE StaticDerivativeShapeInferer is allocated for each subgraph,
+ // so it does not support models that have controlflow operations yet.
+ for (auto &&pair : lowered_subgs)
+ {
+ auto &lowered_subg = pair.second;
+ auto inferer = std::make_unique<StaticDerivativeShapeInferer>(lowered_subg.get());
+ inferer->infer();
+ inferer->dump();
+ }
+ }
+
+ // Shape validation
+ for (const auto &pair : lowered_subgs)
+ {
+ auto &lowered_subg = pair.second;
+ compiler::ShapeValidator{lowered_subg->graph()}();
+ }
+
+ // TODO Validate shapes of derivative tensors
+
+ // Create optimizer
+ // TODO Set properties of optimizer
+ std::shared_ptr<exec::train::optimizer::Optimizer> optimizer;
+ const auto &optim_info = _training_info.optimizerInfo();
+ if (optim_info.optim_code == exec::train::optimizer::OptimizerCode::SGD)
+ optimizer = std::make_shared<exec::train::optimizer::SGD>(optim_info.learning_rate);
+ else
+ throw std::runtime_error("Invalid optimizer type, " +
+ exec::train::optimizer::toString(optim_info.optim_code));
+
+ /*************************************************************
+ * Backend independent analysis & optimization phase finished
+ *************************************************************/
+ auto executors = std::make_shared<exec::train::TrainableExecutors>();
+ for (auto &&pair : lowered_subgs)
+ {
+ auto const model_index = ir::ModelIndex{0};
+ auto const subg_index = pair.first;
+ auto &lowered_subg = pair.second;
+ auto const indexed_ranks = lowered_subg->indexed_ranks();
+
+ ir::OperationDumper dumper("Executor generation of Subgraph " +
+ std::to_string(subg_index.value()));
+ lowered_subg->graph().operations().iterate(
+ [&](const ir::OperationIndex &, const ir::IOperation &op) { op.accept(dumper); });
+
+ ExecutorFactoryArgs args;
+ args.tracing_ctx = tracing_ctx.get();
+ args.options = _options;
+ args.model_index = model_index;
+ args.custom_kernel_builder = custom_kernel_builder;
+ auto executor = std::unique_ptr<exec::IExecutor>{
+ ExecutorFactory::get().create(std::move(lowered_subg), executors, args, optimizer)};
+ executor->setIndexedRanks(indexed_ranks);
+ executors->emplace(model_index, subg_index, std::move(executor));
+ }
+
+ /********************************
+ * Code generation phase finished
+ ********************************/
+ return std::make_shared<CompilerArtifact>(executors, std::move(tracing_ctx));
+}
+
+} // namespace train
+} // namespace compiler
+} // namespace onert
diff --git a/runtime/onert/core/src/compiler/train/TrainingCompiler.h b/runtime/onert/core/src/compiler/train/TrainingCompiler.h
new file mode 100644
index 000000000..b93437217
--- /dev/null
+++ b/runtime/onert/core/src/compiler/train/TrainingCompiler.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file TrainingCompiler.h
+ * @brief This file contains TrainingCompiler class to define and run compilation phase
+ */
+
+#ifndef __ONERT_COMPILER_TRAIN_TRAINING_COMPILER_H_
+#define __ONERT_COMPILER_TRAIN_TRAINING_COMPILER_H_
+
+#include "compiler/CompilerOptions.h"
+#include "compiler/ICompiler.h"
+#include "compiler/train/TrainingInfo.h"
+#include "ir/NNPkg.h"
+
+namespace onert
+{
+namespace compiler
+{
+namespace train
+{
+
+/**
+ * @brief Class to compile NN package
+ */
+class TrainingCompiler : public ICompiler
+{
+public:
+ /**
+ * @brief Construct a new TrainingCompiler object for single model
+ * @param[in] model model to compile
+ * @param[in] inference_compiler Compiler for inference
+ * @param[in] coptions Compiler Options
+ * @param[in] training_info Training information
+ */
+ explicit TrainingCompiler(const std::shared_ptr<ir::NNPkg> &nnpkg,
+ std::vector<std::unique_ptr<CompilerOptions>> &copts,
+ const TrainingInfo &training_info);
+
+ /**
+ * @brief Default Construct
+ *
+ */
+ TrainingCompiler(void) = delete;
+
+ /**
+ * @brief Destroy the TrainingCompiler object
+ */
+ ~TrainingCompiler() = default;
+
+public:
+ /**
+ * @brief Do compilation with the options
+ *
+ * @return std::shared_ptr<CompilerArtifact> Executors as a result of compilation
+ */
+ std::shared_ptr<CompilerArtifact> compile(void);
+
+private:
+ std::shared_ptr<ir::Model> _model;
+ CompilerOptions *_options;
+ const TrainingInfo _training_info;
+};
+
+} // namespace train
+} // namespace compiler
+} // namespace onert
+
+#endif // __ONERT_COMPILER_TRAIN_TRAINING_COMPILER_H_
diff --git a/runtime/onert/core/src/compiler/train/UntrainableOperationConverter.cc b/runtime/onert/core/src/compiler/train/UntrainableOperationConverter.cc
new file mode 100644
index 000000000..6a5a052b6
--- /dev/null
+++ b/runtime/onert/core/src/compiler/train/UntrainableOperationConverter.cc
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "UntrainableOperationConverter.h"
+
+#include "ir/train/operation/UntrainableOperation.h"
+
+namespace onert
+{
+namespace compiler
+{
+namespace train
+{
+
+UntrainableOperationConverter::UntrainableOperationConverter(ir::train::TrainableGraph &tgraph)
+ : _tgraph{tgraph}, _return_op{nullptr}
+{
+}
+
+std::unique_ptr<ir::train::ITrainableOperation> UntrainableOperationConverter::
+operator()(const ir::IOperation &op)
+{
+ op.accept(*this);
+
+ return std::move(_return_op);
+}
+
+#define OP(InternalName) \
+ void UntrainableOperationConverter::visit(const ir::operation::InternalName &node) \
+ { \
+ _return_op = \
+ std::make_unique<ir::train::operation::UntrainableOperation<ir::operation::InternalName>>( \
+ node); \
+ }
+#include "ir/Operations.lst"
+#undef OP
+
+} // namespace train
+} // namespace compiler
+} // namespace onert
diff --git a/runtime/onert/core/src/compiler/train/UntrainableOperationConverter.h b/runtime/onert/core/src/compiler/train/UntrainableOperationConverter.h
new file mode 100644
index 000000000..e960b3831
--- /dev/null
+++ b/runtime/onert/core/src/compiler/train/UntrainableOperationConverter.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_COMPILER_TRAIN_UNTRAINABLE_OPERATION_CONVERTER_H__
+#define __ONERT_COMPILER_TRAIN_UNTRAINABLE_OPERATION_CONVERTER_H__
+
+#include "ir/Operations.Include.h"
+#include "ir/OperationVisitor.h"
+#include "ir/train/TrainableGraph.h"
+
+#include <memory>
+
+namespace onert
+{
+namespace compiler
+{
+namespace train
+{
+
+class UntrainableOperationConverter : public ir::OperationVisitor
+{
+public:
+ UntrainableOperationConverter(ir::train::TrainableGraph &tgraph);
+ std::unique_ptr<ir::train::ITrainableOperation> operator()(const ir::IOperation &op);
+
+#define OP(InternalName) void visit(const ir::operation::InternalName &node);
+#include "ir/Operations.lst"
+#undef OP
+
+protected:
+ ir::train::TrainableGraph &_tgraph;
+ std::unique_ptr<ir::train::ITrainableOperation> _return_op;
+};
+
+} // namespace train
+} // namespace compiler
+} // namespace onert
+
+#endif // __ONERT_COMPILER_TRAIN_UNTRAINABLE_OPERATION_CONVERTER_H__
diff --git a/runtime/onert/core/src/compiler/train/pass/LossInsertionPass.cc b/runtime/onert/core/src/compiler/train/pass/LossInsertionPass.cc
new file mode 100644
index 000000000..3e01a9739
--- /dev/null
+++ b/runtime/onert/core/src/compiler/train/pass/LossInsertionPass.cc
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "LossInsertionPass.h"
+
+#include "ir/train/TrainableGraph.h"
+#include "ir/train/operation/Loss.h"
+
+namespace onert
+{
+namespace compiler
+{
+namespace train
+{
+namespace pass
+{
+
+void LossInsertionPass::run()
+{
+ const auto &loss_info = _training_info->lossInfo();
+
+ ir::operation::Loss::Param param;
+ param.op_type = loss_info.type;
+
+ if (_trainable_graph.getOutputs().size() != 1)
+ {
+ throw std::runtime_error("LossInsertionPass: Not supported multiple outputs");
+ }
+
+ // TODO Consider SparseCategoricalCrossentropy y_true shape
+ // SparseCategoricalCrossentropy loss has a different y_true shape than y_pred.
+
+ // TODO Implement Loop [0, getOutputs().size())
+ // index: a loop index
+ const auto index = 0;
+ const auto &y_pred_index = _trainable_graph.getOutputs().at(index);
+ const auto &y_pred = _trainable_graph.operands().at(y_pred_index);
+ const auto &shape = y_pred.shape();
+ const auto &type_info = y_pred.typeInfo();
+ auto y_true_index = _trainable_graph.addOperand(shape, type_info);
+ ir::OperandIndexSequence inputs{y_pred_index, y_true_index};
+
+ // TODO Consider Reduction
+ // Some types of Reduction have the same shape y_true and output.
+
+ const ir::TypeInfo float_op(ir::DataType::FLOAT32);
+ auto output_index = _trainable_graph.addOperand(ir::Shape{1}, float_op);
+ ir::OperandIndexSequence outputs{output_index};
+
+ auto loss_op = std::make_unique<ir::operation::Loss>(inputs, outputs, param);
+ auto trainable_loss_op = std::make_unique<ir::train::operation::Loss>(*loss_op);
+
+ _trainable_graph.addOperation(std::move(trainable_loss_op));
+
+ _trainable_graph.addInput(y_true_index);
+
+ // TODO Add loss as many as output size
+ _trainable_graph.addLoss(output_index, ir::IOIndex{index});
+}
+
+} // namespace pass
+} // namespace train
+} // namespace compiler
+} // namespace onert
diff --git a/runtime/onert/core/src/compiler/train/pass/LossInsertionPass.h b/runtime/onert/core/src/compiler/train/pass/LossInsertionPass.h
new file mode 100644
index 000000000..ed4d60c96
--- /dev/null
+++ b/runtime/onert/core/src/compiler/train/pass/LossInsertionPass.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_COMPILER_TRAIN_PASS_LOSS_INSERTION_PASS_H__
+#define __ONERT_COMPILER_TRAIN_PASS_LOSS_INSERTION_PASS_H__
+
+#include "Pass.h"
+
+#include "compiler/train/TrainingInfo.h"
+
+namespace onert
+{
+namespace compiler
+{
+namespace train
+{
+namespace pass
+{
+
+class LossInsertionPass : public Pass
+{
+public:
+ LossInsertionPass(ir::train::TrainableGraph &trainable_graph, const TrainingInfo *training_info,
+ const ir::SubgraphIndex &subg_index)
+ : Pass{trainable_graph, training_info}, _subg_index{subg_index}
+ {
+ }
+
+public:
+ std::string id() final { return "LossInsertionPass"; }
+ void run() final;
+
+private:
+ ir::SubgraphIndex _subg_index;
+};
+
+} // namespace pass
+} // namespace train
+} // namespace compiler
+} // namespace onert
+
+#endif // __ONERT_COMPILER_TRAIN_PASS_LOSS_INSERTION_PASS_H__
diff --git a/runtime/onert/core/src/compiler/train/pass/Pass.h b/runtime/onert/core/src/compiler/train/pass/Pass.h
new file mode 100644
index 000000000..d64c06cf4
--- /dev/null
+++ b/runtime/onert/core/src/compiler/train/pass/Pass.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_COMPILER_TRAIN_PASS_PASS_H__
+#define __ONERT_COMPILER_TRAIN_PASS_PASS_H__
+
+#include "../../pass/IPass.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+class TrainableGraph;
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+namespace onert
+{
+namespace compiler
+{
+namespace train
+{
+
+class TrainingInfo;
+
+namespace pass
+{
+
+class Pass : public compiler::pass::IPass
+{
+public:
+ Pass(ir::train::TrainableGraph &trainable_graph, const TrainingInfo *training_info)
+ : _trainable_graph{trainable_graph}, _training_info{training_info}
+ {
+ }
+ virtual ~Pass() = default;
+
+protected:
+ ir::train::TrainableGraph &_trainable_graph;
+ const TrainingInfo *_training_info;
+};
+
+} // namespace pass
+} // namespace train
+} // namespace compiler
+} // namespace onert
+
+#endif // __ONERT_COMPILER_TRAIN_PASS_PASS_H__
diff --git a/runtime/onert/core/src/dumper/dot/DotBuilder.cc b/runtime/onert/core/src/dumper/dot/DotBuilder.cc
index d4e4d5484..9257434fa 100644
--- a/runtime/onert/core/src/dumper/dot/DotBuilder.cc
+++ b/runtime/onert/core/src/dumper/dot/DotBuilder.cc
@@ -29,7 +29,7 @@ DotBuilder::DotBuilder() {}
void DotBuilder::update(const Node &node_info)
{
add(node_info);
- for (auto edge : node_info.out_edges())
+ for (auto &&edge : node_info.out_edges())
{
addEdge(node_info, *edge);
}
@@ -47,7 +47,7 @@ void DotBuilder::add(const Node &node)
_dot << node.id();
std::stringstream ss;
_dot << "[";
- for (auto attr : node.attributes())
+ for (auto &&attr : node.attributes())
{
_dot << attr.first << "=\"" << attr.second << "\" ";
}
diff --git a/runtime/onert/core/src/dumper/dot/DotDumper.cc b/runtime/onert/core/src/dumper/dot/DotDumper.cc
index 0bb2fa11f..ab77a6c62 100644
--- a/runtime/onert/core/src/dumper/dot/DotDumper.cc
+++ b/runtime/onert/core/src/dumper/dot/DotDumper.cc
@@ -98,10 +98,10 @@ generate_dot_operations(const ir::Graph &graph,
{
ir::OperationIndexMap<std::unique_ptr<Operation>> dot_operations;
const auto &operations = graph.operations();
- operations.iterate([&](const ir::OperationIndex &index, const ir::Operation &op) {
+ operations.iterate([&](const ir::OperationIndex &index, const ir::IOperation &op) {
auto node = std::make_unique<Operation>(index, op);
- for (auto input : op.getInputs())
+ for (auto &&input : op.getInputs())
{
using onert::dumper::dot::Operand;
@@ -113,7 +113,7 @@ generate_dot_operations(const ir::Graph &graph,
input_node->addOutEdge(node.get());
}
- for (auto output : op.getOutputs() | ir::Remove::UNDEFINED)
+ for (auto &&output : op.getOutputs() | ir::Remove::UNDEFINED)
{
using onert::dumper::dot::Operand;
auto &output_node = dot_operands.at(output);
@@ -126,7 +126,7 @@ generate_dot_operations(const ir::Graph &graph,
return dot_operations;
}
-void update_lower_info(const compiler::LoweredGraph &lowered_graph,
+void update_lower_info(const compiler::ILoweredGraph &lowered_graph,
ir::OperandIndexMap<std::unique_ptr<Operand>> *dot_operands)
{
const auto &operands = lowered_graph.graph().operands();
@@ -153,11 +153,11 @@ void update_lower_info(const compiler::LoweredGraph &lowered_graph,
});
}
-void update_lower_info(const compiler::LoweredGraph &lowered_graph,
+void update_lower_info(const compiler::ILoweredGraph &lowered_graph,
ir::OperationIndexMap<std::unique_ptr<Operation>> *dot_operations)
{
const auto &operations = lowered_graph.graph().operations();
- operations.iterate([&](const ir::OperationIndex &index, const ir::Operation &) {
+ operations.iterate([&](const ir::OperationIndex &index, const ir::IOperation &) {
const auto lower_info = lowered_graph.lower_info().operation.getRawPtr(index);
if (lower_info)
{
@@ -213,7 +213,8 @@ void DotDumper::dump(const ir::Graph &graph, const std::string &tag)
dump_to_file(dot_operands, dot_operations, tag);
}
-void DotDumper::dump(const compiler::LoweredGraph &lowered_graph, const std::string &tag)
+// TODO Support derivative tensors
+void DotDumper::dump(const compiler::ILoweredGraph &lowered_graph, const std::string &tag)
{
if (_level == Level::OFF)
{
diff --git a/runtime/onert/core/src/dumper/dot/DotDumper.h b/runtime/onert/core/src/dumper/dot/DotDumper.h
index 6249010d3..fca5f356c 100644
--- a/runtime/onert/core/src/dumper/dot/DotDumper.h
+++ b/runtime/onert/core/src/dumper/dot/DotDumper.h
@@ -15,7 +15,7 @@
*/
#include "ir/Graph.h"
-#include "compiler/LoweredGraph.h"
+#include "compiler/ILoweredGraph.h"
#ifndef __ONERT_DUMPER_DOT_DOT_DUMPER_H__
#define __ONERT_DUMPER_DOT_DOT_DUMPER_H__
@@ -57,7 +57,7 @@ public:
* @param[in] tag The name of dot file that would be created
* @return N/A
*/
- void dump(const compiler::LoweredGraph &lowered_graph, const std::string &tag);
+ void dump(const compiler::ILoweredGraph &lowered_graph, const std::string &tag);
private:
Level _level;
diff --git a/runtime/onert/core/src/dumper/dot/OperationNode.cc b/runtime/onert/core/src/dumper/dot/OperationNode.cc
index 87c5ba148..2ef08c9c6 100644
--- a/runtime/onert/core/src/dumper/dot/OperationNode.cc
+++ b/runtime/onert/core/src/dumper/dot/OperationNode.cc
@@ -31,7 +31,7 @@ namespace dot
const std::string Operation::OPERATION_SHAPE = "rect";
const std::string Operation::BG_COLOR_SCHEME = "pastel18";
-Operation::Operation(const ir::OperationIndex &index, const ir::Operation &node)
+Operation::Operation(const ir::OperationIndex &index, const ir::IOperation &node)
: Node{"operation" + std::to_string(index.value())}
{
setAttribute("label", std::to_string(index.value()) + " : " + node.name());
diff --git a/runtime/onert/core/src/dumper/dot/OperationNode.h b/runtime/onert/core/src/dumper/dot/OperationNode.h
index 74a37d3fb..d9292ad0c 100644
--- a/runtime/onert/core/src/dumper/dot/OperationNode.h
+++ b/runtime/onert/core/src/dumper/dot/OperationNode.h
@@ -25,7 +25,7 @@
#define __ONERT_DUMPER_DOT_DOT_NODE_INFO_H__
#include "Node.h"
-#include "ir/Operation.h"
+#include "ir/IOperation.h"
#include "ir/Index.h"
namespace onert
@@ -52,7 +52,7 @@ public:
* @param[in] index operation index
* @param[in] node operation object
*/
- Operation(const ir::OperationIndex &index, const ir::Operation &node);
+ Operation(const ir::OperationIndex &index, const ir::IOperation &node);
};
} // namespace dot
diff --git a/runtime/onert/core/src/dumper/h5/Dumper.cc b/runtime/onert/core/src/dumper/h5/Dumper.cc
new file mode 100644
index 000000000..5e12c2dbb
--- /dev/null
+++ b/runtime/onert/core/src/dumper/h5/Dumper.cc
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Dumper.h"
+
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+
+namespace onert
+{
+namespace dumper
+{
+namespace h5
+{
+
+Dumper::Dumper(const std::string &filepath) : _file{filepath, H5F_ACC_CREAT | H5F_ACC_RDWR} {}
+
+} // namespace h5
+} // namespace dumper
+} // namespace onert
diff --git a/runtime/onert/core/src/dumper/h5/Dumper.h b/runtime/onert/core/src/dumper/h5/Dumper.h
new file mode 100644
index 000000000..53d0e0332
--- /dev/null
+++ b/runtime/onert/core/src/dumper/h5/Dumper.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_DUMPER_H5_DUMPER_H__
+#define __ONERT_DUMPER_H5_DUMPER_H__
+
+#include "exec/MinMaxMap.h"
+
+#include <H5Cpp.h>
+#include <string>
+
+namespace onert
+{
+namespace dumper
+{
+namespace h5
+{
+
+class Dumper
+{
+public:
+ /**
+ * @brief Construct dumper
+ *
+ * @param[in] path filepath to dump
+ * @throw H5::FileIException on error during file open/create
+ */
+ Dumper(const std::string &filepath);
+
+protected:
+ H5::H5File _file;
+};
+
+} // namespace h5
+} // namespace dumper
+} // namespace onert
+
+#endif // __ONERT_DUMPER_H5_DUMPER_H__
diff --git a/runtime/onert/core/src/dumper/h5/MinMaxDumper.cc b/runtime/onert/core/src/dumper/h5/MinMaxDumper.cc
new file mode 100644
index 000000000..8a9de9f95
--- /dev/null
+++ b/runtime/onert/core/src/dumper/h5/MinMaxDumper.cc
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MinMaxDumper.h"
+
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+
+namespace onert
+{
+namespace dumper
+{
+namespace h5
+{
+
+static const char *h5_value_grpname = "value";
+
+/*
+ * ensure grp_name exists in parent
+ */
+H5::Group ensureGroup(H5::Group parent, const char *child)
+{
+ H5::Exception::dontPrint();
+ try
+ {
+ return parent.openGroup(child);
+ }
+ catch (H5::Exception &e)
+ {
+ return parent.createGroup(child);
+ }
+}
+
+MinMaxDumper::MinMaxDumper(const std::string &filepath) : Dumper(filepath)
+{
+ auto root_grp = _file.openGroup("/");
+ ensureGroup(root_grp, h5_value_grpname);
+}
+
+void MinMaxDumper::dump(const exec::SMMinMaxMap &mmmap) const
+{
+ auto val_grp = _file.openGroup(h5_value_grpname);
+ auto num_run = val_grp.getNumObjs();
+ auto num_grp = val_grp.createGroup(std::to_string(num_run));
+ auto model_grp = ensureGroup(num_grp, "0");
+ hsize_t dims[] = {2};
+ H5::DataSpace dspace(1, dims); // rank=1, dim(0)=2, {min, max}
+ for (auto &&e : mmmap)
+ {
+ // key = {subg_idx, op_idx} = e.first
+ const auto subg_idx = e.first.first.value();
+ const auto op_idx = e.first.second.value();
+ auto subg_grp = ensureGroup(model_grp, std::to_string(subg_idx).c_str());
+ auto op_dset = subg_grp.createDataSet(std::to_string(op_idx), H5::PredType::IEEE_F32BE, dspace);
+ op_dset.write(e.second.data, H5::PredType::NATIVE_FLOAT);
+ }
+}
+
+} // namespace h5
+} // namespace dumper
+} // namespace onert
diff --git a/runtime/onert/core/src/dumper/h5/MinMaxDumper.h b/runtime/onert/core/src/dumper/h5/MinMaxDumper.h
new file mode 100644
index 000000000..1f1b27c6e
--- /dev/null
+++ b/runtime/onert/core/src/dumper/h5/MinMaxDumper.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_DUMPER_H5_MINMAX_DUMPER_H__
+#define __ONERT_DUMPER_H5_MINMAX_DUMPER_H__
+
+#include "exec/MinMaxMap.h"
+#include "Dumper.h"
+
+#include <H5Cpp.h>
+#include <string>
+
+namespace onert
+{
+namespace dumper
+{
+namespace h5
+{
+
+// The hierachy of single model minmax h5 file
+//
+// GROUP /
+// GROUP value
+// └── GROUP run_idx
+// └── GROUP model_idx
+// └── GROUP subg_idx
+// └── DATASET op_idx
+// DATATYPE Float32
+// DATASPACE (2)
+// DATA { min, max }
+// GROUP name (optional, for debug)
+// └── GROUP model_idx
+// └── GROUP subg_idx
+// └── ATTRIBUTE op_idx
+// DATATYPE String
+// DATA { "model/your/op/name"}
+//
+class MinMaxDumper : private Dumper
+{
+public:
+ MinMaxDumper(const std::string &filepath);
+ /**
+ * @brief Dump minmax map
+ *
+ * @param[in] map single model minmax map
+ */
+ void dump(const exec::SMMinMaxMap &map) const;
+
+private:
+ H5::Group _val_grp;
+};
+
+} // namespace h5
+} // namespace dumper
+} // namespace onert
+
+#endif // __ONERT_DUMPER_H5_MINMAX_DUMPER_H__
diff --git a/runtime/onert/core/src/dumper/text/GraphDumper.cc b/runtime/onert/core/src/dumper/text/GraphDumper.cc
index 80cfbbc34..6bd7904aa 100644
--- a/runtime/onert/core/src/dumper/text/GraphDumper.cc
+++ b/runtime/onert/core/src/dumper/text/GraphDumper.cc
@@ -18,6 +18,9 @@
#include "ir/Graph.h"
#include "compiler/LoweredGraph.h"
+#ifdef ONERT_TRAIN
+#include "compiler/train/LoweredTrainableGraph.h"
+#endif // ONERT_TRAIN
#include "util/logging.h"
#include "misc/string_helpers.h"
@@ -34,7 +37,7 @@ namespace
std::string formatOperandIndexSequence(const ir::OperandIndexSequence &seq)
{
std::vector<std::string> strs;
- for (auto ind : seq)
+ for (auto &&ind : seq)
strs.push_back(dumper::text::formatOperandBrief(ind));
return nnfw::misc::join(strs.begin(), strs.end(), ", ");
}
@@ -56,10 +59,9 @@ std::string formatOperand(const ir::Graph &, ir::OperandIndex ind)
return ss.str();
}
-std::string formatOperation(const ir::Graph &graph, ir::OperationIndex ind)
+std::string formatOperation(const ir::IOperation &op, ir::OperationIndex ind)
{
std::stringstream ss;
- const auto &op = graph.operations().at(ind);
ss << formatOperandIndexSequence(op.getOutputs());
ss << " = ";
@@ -69,13 +71,21 @@ std::string formatOperation(const ir::Graph &graph, ir::OperationIndex ind)
return ss.str();
}
+std::string formatOperation(const ir::Graph &graph, ir::OperationIndex ind)
+{
+ std::stringstream ss;
+ const auto &op = graph.operations().at(ind);
+ return formatOperation(op, ind);
+}
+
void dumpGraph(const ir::Graph &graph)
{
VERBOSE(GraphDumper) << "{\n";
auto ops_topol = graph.topolSortOperations();
- for (auto op_ind : ops_topol)
+ for (auto &&op_ind : ops_topol)
{
- VERBOSE(GraphDumper) << " " << formatOperation(graph, op_ind) << "\n";
+ const auto &op = graph.operations().at(op_ind);
+ VERBOSE(GraphDumper) << " " << formatOperation(op, op_ind) << "\n";
}
VERBOSE(GraphDumper) << "}\n";
VERBOSE(GraphDumper) << std::endl;
@@ -87,6 +97,14 @@ void dumpLoweredGraph(const compiler::LoweredGraph &lgraph)
dumpGraph(lgraph.graph());
}
+#ifdef ONERT_TRAIN
+void dumpLoweredGraph(const compiler::train::LoweredTrainableGraph &lgraph)
+{
+ // TODO Graph dump with backend info
+ dumpGraph(lgraph.graph());
+}
+#endif // ONERT_TRAIN
+
} // namespace text
} // namespace dumper
} // namespace onert
diff --git a/runtime/onert/core/src/dumper/text/GraphDumper.h b/runtime/onert/core/src/dumper/text/GraphDumper.h
index 0501ff050..ab0061465 100644
--- a/runtime/onert/core/src/dumper/text/GraphDumper.h
+++ b/runtime/onert/core/src/dumper/text/GraphDumper.h
@@ -24,7 +24,8 @@ namespace onert
namespace ir
{
class Graph;
-}
+struct IOperation;
+} // namespace ir
} // namespace onert
namespace onert
@@ -32,7 +33,14 @@ namespace onert
namespace compiler
{
class LoweredGraph;
-}
+
+#ifdef ONERT_TRAIN
+namespace train
+{
+class LoweredTrainableGraph;
+} // namespace train
+#endif // ONERT_TRAIN
+} // namespace compiler
} // namespace onert
namespace onert
@@ -47,6 +55,9 @@ std::string formatOperand(const ir::Graph &, ir::OperandIndex ind);
std::string formatOperation(const ir::Graph &graph, ir::OperationIndex ind);
void dumpGraph(const ir::Graph &graph);
void dumpLoweredGraph(const compiler::LoweredGraph &lgraph);
+#ifdef ONERT_TRAIN
+void dumpLoweredGraph(const compiler::train::LoweredTrainableGraph &lgraph);
+#endif // ONERT_TRAIN
} // namespace text
} // namespace dumper
diff --git a/runtime/onert/core/src/exec/DataflowExecutor.cc b/runtime/onert/core/src/exec/DataflowExecutor.cc
index 8dac1219e..e0b00077f 100644
--- a/runtime/onert/core/src/exec/DataflowExecutor.cc
+++ b/runtime/onert/core/src/exec/DataflowExecutor.cc
@@ -60,7 +60,7 @@ void DataflowExecutor::emplaceToReadyJobs(const uint32_t &id)
void DataflowExecutor::notify(uint32_t finished_job_id)
{
- for (auto id : _output_info[finished_job_id])
+ for (auto &&id : _output_info[finished_job_id])
{
assert(_input_info[id] > 0);
auto count = --_input_info[id];
@@ -90,7 +90,7 @@ DataflowExecutor::DataflowExecutor(std::unique_ptr<compiler::LoweredGraph> lower
uint32_t next_job_index = 0;
std::unordered_map<ir::OperationIndex, uint32_t> op_to_job;
const auto &operations = _lowered_graph->graph().operations();
- operations.iterate([&](const ir::OperationIndex &op_ind, const ir::Operation &) {
+ operations.iterate([&](const ir::OperationIndex &op_ind, const ir::IOperation &) {
VERBOSE(DataflowExecutor) << "Create a job " << next_job_index << " with Operation " << op_ind
<< std::endl;
_finished_jobs.emplace_back(
@@ -102,12 +102,12 @@ DataflowExecutor::DataflowExecutor(std::unique_ptr<compiler::LoweredGraph> lower
_output_info.resize(next_job_index);
_initial_input_info.resize(next_job_index, 0);
- operations.iterate([&](const ir::OperationIndex &op_ind, const ir::Operation &op) {
+ operations.iterate([&](const ir::OperationIndex &op_ind, const ir::IOperation &op) {
auto job_index = op_to_job[op_ind];
- for (auto output : op.getOutputs())
+ for (auto &&output : op.getOutputs())
{
// Update output and input info
- operations.iterate([&](const ir::OperationIndex &op_cur_ind, const ir::Operation &op_cur) {
+ operations.iterate([&](const ir::OperationIndex &op_cur_ind, const ir::IOperation &op_cur) {
if (op_cur.getInputs().contains(output))
{
auto dep_index = op_to_job[op_cur_ind];
diff --git a/runtime/onert/core/src/exec/DynamicShapeInferer.cc b/runtime/onert/core/src/exec/DynamicShapeInferer.cc
index fb8058d23..78b21cf49 100644
--- a/runtime/onert/core/src/exec/DynamicShapeInferer.cc
+++ b/runtime/onert/core/src/exec/DynamicShapeInferer.cc
@@ -253,7 +253,7 @@ void DynamicShapeInferer::visit(const ir::operation::Concat &op)
So, only when all inputs are static, we can skip dynamic shape inference.
*/
bool all_static = true;
- for (auto input_ind : op.getInputs())
+ for (auto &&input_ind : op.getInputs())
{
auto input = _tensor_registry->getITensor(input_ind);
if (input->is_dynamic())
@@ -290,7 +290,7 @@ void DynamicShapeInferer::visit(const ir::operation::Concat &op)
auto first_input_ind = op.getInputs().at(0);
auto first_input = _tensor_registry->getITensor(first_input_ind);
- for (auto input_ind : op.getInputs())
+ for (auto &&input_ind : op.getInputs())
{
auto input = _tensor_registry->getITensor(input_ind);
if (input != first_input && !isConcatible(first_input, input, op.param().axis))
@@ -300,7 +300,7 @@ void DynamicShapeInferer::visit(const ir::operation::Concat &op)
// getting output shape
onert::shape_inference::Shapes in_shapes;
- for (auto input_ind : op.getInputs())
+ for (auto &&input_ind : op.getInputs())
{
auto input = _tensor_registry->getITensor(input_ind);
ir::Shape shape = input->getShape();
@@ -1042,7 +1042,7 @@ void DynamicShapeInferer::visit(const ir::operation::Split &op)
// Return if all tensors are not dynamic
bool has_dynamic = false;
- for (const auto output_idx : op.getOutputs())
+ for (const auto &output_idx : op.getOutputs())
{
auto output = _tensor_registry->getITensor(output_idx);
has_dynamic |= output->is_dynamic();
diff --git a/runtime/onert/core/src/exec/ExecTime.test.cc b/runtime/onert/core/src/exec/ExecTime.test.cc
index 1f7152e7b..939184e4e 100644
--- a/runtime/onert/core/src/exec/ExecTime.test.cc
+++ b/runtime/onert/core/src/exec/ExecTime.test.cc
@@ -34,7 +34,7 @@ struct MockConfig : public IConfig
std::string id() override { return "b1"; }
bool initialize() override { return true; };
bool supportPermutation() override { return false; }
- ir::Layout supportLayout(const ir::Operation &, ir::Layout) override
+ ir::Layout supportLayout(const ir::IOperation &, ir::Layout) override
{
return ir::Layout::UNKNOWN;
}
diff --git a/runtime/onert/core/src/exec/Execution.cc b/runtime/onert/core/src/exec/Execution.cc
index 7d5b406ef..1384c9fdc 100644
--- a/runtime/onert/core/src/exec/Execution.cc
+++ b/runtime/onert/core/src/exec/Execution.cc
@@ -16,6 +16,8 @@
#include "exec/Execution.h"
+#include "train/TrainableExecutors.h"
+
#include "util/logging.h"
namespace onert
@@ -151,6 +153,35 @@ void Execution::waitFinish()
bool Execution::isFinished(void) const { return finished; }
+#ifdef ONERT_TRAIN
+void Execution::train(uint32_t training_step)
+{
+ auto execs = dynamic_cast<exec::train::TrainableExecutors *>(_executors.get());
+ if (!execs)
+ {
+ throw std::runtime_error{"Supported only TrainableExecutors"};
+ }
+
+ VERBOSE(Execution) << "Start training" << std::endl;
+
+ execs->train(_io_desc, training_step);
+ finished = true;
+
+ VERBOSE(Execution) << "training finished" << std::endl;
+}
+
+float Execution::getLoss(const ir::IOIndex &ind)
+{
+ auto execs = dynamic_cast<exec::train::TrainableExecutors *>(_executors.get());
+ if (!execs)
+ {
+ throw std::runtime_error{"Supported only TrainableExecutors"};
+ }
+
+ return execs->getLoss(ind);
+}
+#endif // ONERT_TRAIN
+
ir::Shape Execution::getInputShape(ir::IOIndex ind) const
{
auto itr = _io_desc.dynamic_input_shapes.find(ind);
@@ -180,5 +211,16 @@ ir::Shape Execution::getOutputShape(ir::IOIndex ind) const
return output_desc->info.shape();
}
+size_t Execution::getInputTotalSize(ir::IOIndex ind) const
+{
+ // TODO Support dynamic shape
+ return _executors->inputInfo(ind).total_size();
+}
+
+size_t Execution::getOutputTotalSize(ir::IOIndex ind) const
+{
+ return _executors->outputInfo(ind).total_size();
+}
+
} // namespace exec
} // namespace onert
diff --git a/runtime/onert/core/src/exec/ExecutionObservers.cc b/runtime/onert/core/src/exec/ExecutionObservers.cc
index 9abde7ba4..5245518a0 100644
--- a/runtime/onert/core/src/exec/ExecutionObservers.cc
+++ b/runtime/onert/core/src/exec/ExecutionObservers.cc
@@ -28,7 +28,7 @@
namespace
{
-void setUserData(const onert::ir::Graph &g, const onert::ir::Operation *op,
+void setUserData(const onert::ir::Graph &g, const onert::ir::IOperation *op,
decltype(EventCollector::Event::userData) &data)
{
// From a tensor of shape [a, b, c], this will return a string "shape(a b c)".
diff --git a/runtime/onert/core/src/exec/ExecutionObservers.h b/runtime/onert/core/src/exec/ExecutionObservers.h
index 91fbac323..7e93ecf7c 100644
--- a/runtime/onert/core/src/exec/ExecutionObservers.h
+++ b/runtime/onert/core/src/exec/ExecutionObservers.h
@@ -24,7 +24,7 @@
#include "exec/IExecutor.h"
#include "ir/Index.h"
-#include "ir/Operation.h"
+#include "ir/IOperation.h"
#include "util/ITimer.h"
#include "util/TracingCtx.h"
diff --git a/runtime/onert/core/src/exec/ExecutorBase.cc b/runtime/onert/core/src/exec/ExecutorBase.cc
index 515cf8e48..ad0073477 100644
--- a/runtime/onert/core/src/exec/ExecutorBase.cc
+++ b/runtime/onert/core/src/exec/ExecutorBase.cc
@@ -35,7 +35,7 @@ ExecutorBase::ExecutorBase(std::unique_ptr<compiler::LoweredGraph> &&lowered_gra
{
auto build_tensor_list = [&](const auto &ind_seq, auto &tensors) {
assert(tensors.empty());
- for (auto ind : ind_seq)
+ for (auto &&ind : ind_seq)
{
backend::ITensor *tensor = tensor_regs.getITensor(ind);
assert(tensor != nullptr);
diff --git a/runtime/onert/core/src/exec/ExecutorBase.h b/runtime/onert/core/src/exec/ExecutorBase.h
index 7aee3d9ee..4f97de922 100644
--- a/runtime/onert/core/src/exec/ExecutorBase.h
+++ b/runtime/onert/core/src/exec/ExecutorBase.h
@@ -77,6 +77,7 @@ public:
{
return _output_tensors;
}
+ backend::BackendContexts &getBackendContexts() { return _backend_contexts; }
protected:
/**
diff --git a/runtime/onert/core/src/exec/Executors.cc b/runtime/onert/core/src/exec/Executors.cc
index 7edd5aaa2..8a1be3df4 100644
--- a/runtime/onert/core/src/exec/Executors.cc
+++ b/runtime/onert/core/src/exec/Executors.cc
@@ -147,7 +147,7 @@ void Executors::checkSupportedMultimodel() const
// Assumption: edges
// m1 < m2, s1 == 0 and s2 == 0 if edge 'm1:s1:o1 -> m2:s2:o2'
- for (auto edge : _model_edges->edges)
+ for (auto &&edge : _model_edges->edges)
{
auto const model_from = std::get<ir::ModelIndex>(edge.from);
auto const model_to = std::get<ir::ModelIndex>(edge.to);
diff --git a/runtime/onert/core/src/exec/FunctionSequence.cc b/runtime/onert/core/src/exec/FunctionSequence.cc
index f87c271f7..578123a54 100644
--- a/runtime/onert/core/src/exec/FunctionSequence.cc
+++ b/runtime/onert/core/src/exec/FunctionSequence.cc
@@ -16,7 +16,6 @@
#include "exec/FunctionSequence.h"
-#include "ir/Operation.h"
#include "backend/ITensorRegistry.h"
#include "util/logging.h"
diff --git a/runtime/onert/core/src/exec/LinearExecutor.h b/runtime/onert/core/src/exec/LinearExecutor.h
index a833466da..cc073411a 100644
--- a/runtime/onert/core/src/exec/LinearExecutor.h
+++ b/runtime/onert/core/src/exec/LinearExecutor.h
@@ -52,7 +52,7 @@ public:
const std::vector<ir::OperationIndex> &order, const util::TracingCtx *tracing_ctx)
: ExecutorBase{std::move(lowered_graph), std::move(backend_contexts), tensor_regs, tracing_ctx}
{
- for (auto index : order)
+ for (auto &&index : order)
{
_code.emplace_back(std::move(code_map.at(index)));
}
diff --git a/runtime/onert/core/src/exec/MinMaxRecorder.cc b/runtime/onert/core/src/exec/MinMaxRecorder.cc
new file mode 100644
index 000000000..88fc104d1
--- /dev/null
+++ b/runtime/onert/core/src/exec/MinMaxRecorder.cc
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MinMaxRecorder.h"
+
+#include "backend/ITensor.h"
+
+#include <cassert>
+#include <cmath>
+
+namespace onert
+{
+namespace exec
+{
+
+MinMaxRecorder::MinMaxRecorder(const std::string &minmax_filepath, const ir::Graph &graph,
+ const backend::BackendContexts &backend_contexts)
+ : _graph{graph}, _backend_contexts{backend_contexts}, _h5dumper(minmax_filepath)
+{
+}
+
+void MinMaxRecorder::handleJobEnd(IExecutor *, ir::SubgraphIndex subg_idx,
+ ir::OperationIndex op_idx, const backend::Backend *backend)
+{
+ const auto &tensor_reg = _backend_contexts.at(backend)->tensor_registry;
+ const auto &op = _graph.operations().at(op_idx);
+ const auto &outputs = op.getOutputs();
+ // TODO: Support multiple output
+ if (outputs.size() != 1)
+ throw std::runtime_error("Only 1 output operator is supported for recording minmax.");
+
+ auto tensor = tensor_reg->getITensor(outputs.at(0));
+
+ // Logic copied from MinMaxObserver.cpp.
+
+ // Filter Ops
+ if (tensor->is_constant())
+ return;
+
+ if (tensor->data_type() != ir::DataType::FLOAT32)
+ return;
+
+ switch (op.opcode())
+ {
+ // Operators with multiple outputs
+ case ir::OpCode::If:
+ case ir::OpCode::Split:
+ case ir::OpCode::SplitV:
+ case ir::OpCode::TopKV2:
+ case ir::OpCode::Unpack:
+ case ir::OpCode::While:
+ return;
+ // NOTE: Sin, Cos, Tanh's output is in [-1, 1]
+ // We may not need to dump those operators.
+ default:; // Do Nothing
+ }
+
+ // Otherwise, dump!
+ assert(tensor->data_type() == ir::DataType::FLOAT32);
+ const auto data = reinterpret_cast<float *>(tensor->buffer());
+ const auto num_elements = tensor->total_size() / sizeof(float);
+
+ float max = std::numeric_limits<float>::lowest();
+ float min = std::numeric_limits<float>::max();
+
+ bool all_nan = true;
+ for (size_t i = 0; i < num_elements; ++i)
+ {
+ const float number = data[i];
+ if (std::isnan(number))
+ continue;
+
+ if (number == std::numeric_limits<float>::lowest())
+ continue;
+
+ all_nan = false;
+
+ if (number > max)
+ max = number;
+
+ if (number < min)
+ min = number;
+ }
+
+ if (all_nan)
+ throw std::runtime_error("All values are NaN(Not a Number)");
+
+ _minmax_map.append({subg_idx, op_idx}, min, max);
+}
+
+void MinMaxRecorder::handleSubgraphEnd(ir::SubgraphIndex)
+{
+ // It would be better to dump at the end of model execution, not subgraph
+ // But it requires more changes than subgraph.
+ _h5dumper.dump(_minmax_map);
+}
+
+} // namespace exec
+} // namespace onert
diff --git a/runtime/onert/core/src/exec/MinMaxRecorder.h b/runtime/onert/core/src/exec/MinMaxRecorder.h
new file mode 100644
index 000000000..7a0817f5f
--- /dev/null
+++ b/runtime/onert/core/src/exec/MinMaxRecorder.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_EXEC_MINMAX_RECORDER__
+#define __ONERT_EXEC_MINMAX_RECORDER__
+
+#include "ExecutionObservers.h"
+#include "ir/Index.h"
+#include "exec/MinMaxMap.h"
+#include "../dumper/h5/MinMaxDumper.h"
+
+#include <memory>
+
+namespace onert
+{
+namespace exec
+{
+
+class MinMaxRecorder : public IExecutionObserver
+{
+public:
+ MinMaxRecorder(const std::string &minmax_filepath, const ir::Graph &graph,
+ const backend::BackendContexts &backend_contexts);
+ void handleJobBegin(IExecutor *, ir::SubgraphIndex, ir::OperationIndex,
+ const backend::Backend *) override
+ {
+ return;
+ }
+ void handleJobEnd(IExecutor *, ir::SubgraphIndex, ir::OperationIndex,
+ const backend::Backend *) override;
+ void handleSubgraphEnd(ir::SubgraphIndex) override;
+
+private:
+ const ir::Graph &_graph;
+ const backend::BackendContexts &_backend_contexts;
+ dumper::h5::MinMaxDumper _h5dumper;
+ SMMinMaxMap _minmax_map;
+};
+
+} // namespace exec
+} // namespace onert
+
+#endif // __ONERT_EXEC_MINMAX_RECORDER__
diff --git a/runtime/onert/core/src/exec/ParallelScheduler.cc b/runtime/onert/core/src/exec/ParallelScheduler.cc
index 456663f91..538945631 100644
--- a/runtime/onert/core/src/exec/ParallelScheduler.cc
+++ b/runtime/onert/core/src/exec/ParallelScheduler.cc
@@ -30,7 +30,7 @@ ParallelScheduler::ParallelScheduler(const BackendSet &backends)
{
assert(!backends.empty());
- for (auto backend : backends)
+ for (auto &&backend : backends)
{
_thread_pools[backend] = std::make_unique<ThreadPool>();
}
diff --git a/runtime/onert/core/src/exec/train/TrainableExecutor.cc b/runtime/onert/core/src/exec/train/TrainableExecutor.cc
new file mode 100644
index 000000000..9c7e70c29
--- /dev/null
+++ b/runtime/onert/core/src/exec/train/TrainableExecutor.cc
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TrainableExecutor.h"
+#ifdef RUY_PROFILER
+#include "ruy/profiler/instrumentation.h"
+#endif
+
+#include <misc/polymorphic_downcast.h>
+
+namespace onert
+{
+namespace exec
+{
+namespace train
+{
+
+TrainableExecutor::TrainableExecutor(
+ std::unique_ptr<compiler::train::LoweredTrainableGraph> lowered_graph,
+ backend::train::TrainableBackendContexts &&backend_contexts,
+ const compiler::train::TensorRegistries &tensor_regs,
+ compiler::train::TrainableCodeMap &&code_map, const std::vector<ir::OperationIndex> &order,
+ const util::TracingCtx *tracing_ctx)
+ : _lowered_graph{std::move(lowered_graph)}, _backend_contexts{std::move(backend_contexts)},
+ _trainable_graph{_lowered_graph->trainable_graph()}, _tensor_regs{std::move(tensor_regs)},
+ _mutex(), _tracing_ctx(tracing_ctx)
+{
+ auto build_tensor_list = [&](const auto &ind_seq, auto &tensors) {
+ assert(tensors.empty());
+ for (auto &&ind : ind_seq)
+ {
+ backend::ITensor *tensor = tensor_regs.getITensor(ind);
+ assert(tensor != nullptr);
+ auto io_tensor = nnfw::misc::polymorphic_downcast<backend::builtin::IOTensor *>(tensor);
+ tensors.push_back(io_tensor);
+ }
+ };
+ build_tensor_list(_trainable_graph.getInputs(), _input_tensors);
+ build_tensor_list(_trainable_graph.getOutputs(), _output_tensors);
+
+ for (auto &&index : order)
+ {
+ auto &trainable_code = code_map.at(index);
+ _code.emplace_back(std::move(trainable_code));
+ }
+}
+
+void TrainableExecutor::execute(const std::vector<backend::IPortableTensor *> &,
+ const std::vector<backend::IPortableTensor *> &)
+{
+ throw std::runtime_error("TrainableExecutor does not support multiple subgraphs yet");
+}
+
+void TrainableExecutor::forward(const IODescription &desc, bool training)
+{
+ // For thread-safe, use mutex
+ // TODO: if all used backends on this executor are thread-safe,
+ // do not need to use mutex (otherwise, use mutex)
+ std::lock_guard<std::mutex> lock(_mutex);
+
+ // TODO Update IO tensors if desc has dynamic input
+ // Set input(s)
+ assert(_input_tensors.size() == desc.inputs.size());
+ for (uint32_t i = 0; i < _input_tensors.size(); ++i)
+ {
+ auto tensor = _input_tensors[i];
+
+ // TODO Check if (desc.inputs[i] == nullptr)
+ // TODO Better design for ITensor? (we need const_cast as ITensor is writable)
+ tensor->setUserTensor(static_cast<uint8_t *>(const_cast<void *>(desc.inputs[i]->buffer)),
+ desc.inputs[i]->size);
+ }
+
+ if (!training)
+ {
+ // Set output(s)
+ assert(_output_tensors.size() == desc.outputs.size());
+ for (uint32_t i = 0; i < _output_tensors.size(); ++i)
+ {
+ auto tensor = _output_tensors[i];
+
+ if (desc.outputs[i] == nullptr)
+ throw std::runtime_error{"Output " + std::to_string(i) + "'s buffer is not set."};
+ tensor->setUserTensor(static_cast<uint8_t *>(desc.outputs[i]->buffer), desc.outputs[i]->size);
+ }
+ }
+
+ forwardImpl(training);
+
+ // TODO Update output(s) desc if desc has dynamic input
+}
+
+void TrainableExecutor::forwardImpl(bool training)
+{
+ if (_tracing_ctx)
+ {
+ auto profiling_subg_index = _tracing_ctx->getSubgraphIndex(&_trainable_graph.graph());
+
+ _subject.notifySubgraphBegin(profiling_subg_index);
+ for (auto &&code : _code)
+ {
+ const auto backend = code.lower_info->backend();
+// TODO : Move ruy profiler into ExecutionObserver
+#ifdef RUY_PROFILER
+ ruy::profiler::ScopeLabel label(code.op->name());
+#endif
+ _subject.notifyJobBegin(this, profiling_subg_index, code.op_ind, backend);
+
+ auto &tn_seq = code.tn_seq;
+ tn_seq->forward(training);
+
+ _subject.notifyJobEnd(this, profiling_subg_index, code.op_ind, backend);
+ }
+ _subject.notifySubgraphEnd(profiling_subg_index);
+ }
+ else
+ {
+ for (auto &&code : _code)
+ {
+// TODO : Move ruy profiler into ExecutionObserver
+#ifdef RUY_PROFILER
+ ruy::profiler::ScopeLabel label(code.op->name());
+#endif
+ auto &tn_seq = code.tn_seq;
+ tn_seq->forward(training);
+ }
+ }
+}
+
+void TrainableExecutor::backward(const IODescription &, uint32_t training_step)
+{
+ // For thread-safe, use mutex
+ // TODO: if all used backends on this executor are thread-safe,
+ // do not need to use mutex (otherwise, use mutex)
+ std::lock_guard<std::mutex> lock(_mutex);
+
+ backwardImpl(training_step);
+}
+
+void TrainableExecutor::backwardImpl(uint32_t training_step)
+{
+ if (_tracing_ctx)
+ {
+ auto profiling_subg_index = _tracing_ctx->getSubgraphIndex(&_trainable_graph.graph());
+
+ _subject.notifySubgraphBegin(profiling_subg_index);
+ for (auto it = _code.rbegin(); it != _code.rend(); ++it)
+ {
+ const auto &code = *it;
+ const auto backend = code.lower_info->backend();
+// TODO : Move ruy profiler into ExecutionObserver
+#ifdef RUY_PROFILER
+ ruy::profiler::ScopeLabel label(code.op->name());
+#endif
+ _subject.notifyJobBegin(this, profiling_subg_index, code.op_ind, backend);
+
+ auto &tn_seq = code.tn_seq;
+ tn_seq->backward(training_step);
+
+ _subject.notifyJobEnd(this, profiling_subg_index, code.op_ind, backend);
+ }
+ _subject.notifySubgraphEnd(profiling_subg_index);
+ }
+ else
+ {
+ for (auto it = _code.rbegin(); it != _code.rend(); ++it)
+ {
+ const auto &code = *it;
+// TODO : Move ruy profiler into ExecutionObserver
+#ifdef RUY_PROFILER
+ ruy::profiler::ScopeLabel label(code.op->name());
+#endif
+ auto &tn_seq = code.tn_seq;
+ tn_seq->backward(training_step);
+ }
+ }
+}
+
+float TrainableExecutor::getLoss(const ir::IOIndex &pred_io_ind) const
+{
+ const auto &loss_ind = _trainable_graph.getLossIndex(pred_io_ind);
+ if (loss_ind.undefined())
+ throw std::runtime_error{"Loss " + std::to_string(loss_ind.value()) + " is not defined."};
+ backend::ITensor *tensor = _tensor_regs.getITensor(loss_ind);
+ auto loss_buf = reinterpret_cast<float *>(tensor->buffer());
+ return *loss_buf;
+}
+
+} // namespace train
+} // namespace exec
+} // namespace onert
diff --git a/runtime/onert/core/src/exec/train/TrainableExecutor.h b/runtime/onert/core/src/exec/train/TrainableExecutor.h
new file mode 100644
index 000000000..6b645305f
--- /dev/null
+++ b/runtime/onert/core/src/exec/train/TrainableExecutor.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_EXEC_TRAIN_TRAINABLE_EXECUTOR_H_
+#define __ONERT_EXEC_TRAIN_TRAINABLE_EXECUTOR_H_
+
+#include "exec/IExecutor.h"
+
+#include "../ExecutionObservee.h"
+#include "../../compiler/train/TensorRegistries.h"
+
+#include "backend/train/TrainableBackendContext.h"
+#include "compiler/train/TrainableCodeMap.h"
+#include "compiler/train/LoweredTrainableGraph.h"
+#include "ir/Index.h"
+#include "util/TracingCtx.h"
+
+namespace onert
+{
+namespace exec
+{
+namespace train
+{
+
+class TrainableExecutor : public IExecutor
+{
+public:
+ /**
+ * @brief Construct a new TrainableExecutor object
+ * @param lowered_graph LoweredTrainableGraph object
+ * @param tensor_builders Tensor builders that are currently used
+ * @param code_map @c ir::Operation and its code map
+ */
+ TrainableExecutor(std::unique_ptr<compiler::train::LoweredTrainableGraph> lowered_graph,
+ backend::train::TrainableBackendContexts &&backend_contexts,
+ const compiler::train::TensorRegistries &tensor_regs,
+ compiler::train::TrainableCodeMap &&code_map,
+ const std::vector<ir::OperationIndex> &order,
+ const util::TracingCtx *tracing_ctx);
+
+public:
+ const ir::Graph &graph() const final { return _trainable_graph.graph(); }
+
+ void execute(const IODescription &desc) override { forward(desc, false); };
+
+ void execute(const std::vector<backend::IPortableTensor *> &inputs,
+ const std::vector<backend::IPortableTensor *> &outputs) override;
+
+ void forward(const IODescription &desc, bool training);
+ void backward(const IODescription &desc, uint32_t training_step);
+
+ // Used only in Dataflow and Parallel Executors
+ void setIndexedRanks(std::shared_ptr<ir::OperationIndexMap<int64_t>> ranks) final
+ {
+ _indexed_ranks = std::move(ranks);
+ };
+
+ void addObserver(std::unique_ptr<IExecutionObserver> ref) { _subject.add(std::move(ref)); };
+
+ const std::vector<backend::builtin::IOTensor *> &getInputTensors() const override
+ {
+ return _input_tensors;
+ }
+
+ const std::vector<backend::builtin::IOTensor *> &getOutputTensors() const override
+ {
+ return _output_tensors;
+ }
+
+ float getLoss(const ir::IOIndex &pred_io_ind) const;
+
+ backend::train::TrainableBackendContexts &getBackendContexts() { return _backend_contexts; }
+
+private:
+ void forwardImpl(bool training);
+ void backwardImpl(uint32_t training_step);
+
+private:
+ std::vector<compiler::train::TrainableCodeAndInfo> _code;
+ ExecutionObservee _subject;
+ std::shared_ptr<ir::OperationIndexMap<int64_t>> _indexed_ranks;
+ std::unique_ptr<compiler::train::LoweredTrainableGraph> _lowered_graph;
+ backend::train::TrainableBackendContexts _backend_contexts;
+ const ir::train::TrainableGraph &_trainable_graph;
+ compiler::train::TensorRegistries _tensor_regs;
+ std::vector<backend::builtin::IOTensor *> _input_tensors;
+ std::vector<backend::builtin::IOTensor *> _output_tensors;
+ std::mutex _mutex;
+ const util::TracingCtx *_tracing_ctx;
+};
+
+} // namespace train
+} // namespace exec
+} // namespace onert
+
+#endif // __ONERT_EXEC_TRAIN_TRAINABLE_EXECUTOR_H_
diff --git a/runtime/onert/core/src/exec/train/TrainableExecutors.cc b/runtime/onert/core/src/exec/train/TrainableExecutors.cc
new file mode 100644
index 000000000..ba39bf0f0
--- /dev/null
+++ b/runtime/onert/core/src/exec/train/TrainableExecutors.cc
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TrainableExecutors.h"
+
+#include "../../backend/builtin/IOTensor.h"
+
+#include <misc/polymorphic_downcast.h>
+
+namespace onert
+{
+namespace exec
+{
+namespace train
+{
+
+void TrainableExecutors::emplace(const ir::ModelIndex &, const ir::SubgraphIndex &subg_index,
+ std::unique_ptr<IExecutor> exec)
+{
+ std::unique_ptr<TrainableExecutor> t_exec{
+ nnfw::misc::polymorphic_downcast<TrainableExecutor *>(exec.release())};
+ _executors.emplace(subg_index, std::move(t_exec));
+}
+
+TrainableExecutor *TrainableExecutors::at(const ir::ModelIndex &,
+ const ir::SubgraphIndex &subg_index) const
+{
+ return _executors.at(subg_index).get();
+}
+
+uint32_t TrainableExecutors::inputSize() const { return entryExecutor()->getInputTensors().size(); }
+
+uint32_t TrainableExecutors::outputSize() const
+{
+ return entryExecutor()->getOutputTensors().size();
+}
+
+const ir::OperandInfo &TrainableExecutors::inputInfo(const ir::IOIndex &index) const
+{
+ return entryExecutor()->getInputTensors().at(index.value())->orig_info();
+}
+
+const ir::OperandInfo &TrainableExecutors::outputInfo(const ir::IOIndex &index) const
+{
+ return entryExecutor()->getOutputTensors().at(index.value())->orig_info();
+}
+
+void TrainableExecutors::execute(const IODescription &desc)
+{
+ if (_executors.size() > 1)
+ throw std::runtime_error("TrainableExecutors does not support multiple executors yet");
+ entryExecutor()->forward(desc, false);
+
+ // TODO Support multple executors
+}
+
+void TrainableExecutors::train(const IODescription &desc, uint32_t training_step)
+{
+ if (_executors.size() > 1)
+ throw std::runtime_error("TrainableExecutors does not support multiple executors yet");
+ entryExecutor()->forward(desc, true);
+ entryExecutor()->backward(desc, training_step);
+
+ // TODO Support multple executors
+}
+
+float TrainableExecutors::getLoss(const ir::IOIndex &index) const
+{
+ if (_executors.size() > 1)
+ throw std::runtime_error("TrainableExecutors does not support multiple executors yet");
+ return entryExecutor()->getLoss(index);
+}
+
+} // namespace train
+} // namespace exec
+} // namespace onert
diff --git a/runtime/onert/core/src/exec/train/TrainableExecutors.h b/runtime/onert/core/src/exec/train/TrainableExecutors.h
new file mode 100644
index 000000000..db6d198b1
--- /dev/null
+++ b/runtime/onert/core/src/exec/train/TrainableExecutors.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_EXEC_TRAIN_TRAINABLE_EXECUTORS_H__
+#define __ONERT_EXEC_TRAIN_TRAINABLE_EXECUTORS_H__
+
+#include "TrainableExecutor.h"
+#include "exec/IExecutors.h"
+#include "ir/NNPkg.h"
+
+namespace onert
+{
+namespace exec
+{
+namespace train
+{
+
+/**
+ * @brief Class to gather executor set for trainable model NN package
+ */
+class TrainableExecutors : public IExecutors
+{
+public:
+ /**
+ * @brief Construct a new TrainableExecutors object
+ */
+ TrainableExecutors(void) = default;
+ TrainableExecutors(const TrainableExecutors &) = delete;
+ TrainableExecutors(TrainableExecutors &&) = default;
+
+ /**
+ * @brief Destroy the TrainableExecutors object
+ */
+ ~TrainableExecutors() = default;
+
+public:
+ TrainableExecutors &operator=(const TrainableExecutors &) = delete;
+ TrainableExecutors &operator=(TrainableExecutors &&) = default;
+
+public:
+ void emplace(const ir::ModelIndex &model_index, const ir::SubgraphIndex &subg_index,
+ std::unique_ptr<IExecutor> exec) override;
+
+ TrainableExecutor *at(const ir::ModelIndex &model_index,
+ const ir::SubgraphIndex &subg_index) const override;
+
+ TrainableExecutor *entryExecutor() const { return at(ir::ModelIndex{0}, ir::SubgraphIndex{0}); }
+
+ uint32_t inputSize() const override;
+
+ uint32_t outputSize() const override;
+
+ const ir::OperandInfo &inputInfo(const ir::IOIndex &index) const override;
+
+ const ir::OperandInfo &outputInfo(const ir::IOIndex &index) const override;
+
+ void execute(const IODescription &desc) override;
+
+ /**
+ * @brief Train
+ *
+ * @param desc IO information
+ * @param training_step The number of iterations of an training process.
+ * In other words, the number of gradient update.
+ */
+ void train(const IODescription &desc, uint32_t training_step);
+
+ float getLoss(const ir::IOIndex &index) const;
+
+private:
+ // TODO Append model index to ModelIndex
+ std::unordered_map<ir::SubgraphIndex, std::unique_ptr<TrainableExecutor>> _executors;
+};
+
+} // namespace train
+} // namespace exec
+} // namespace onert
+
+#endif // __ONERT_EXEC_TRAIN_TRAINABLE_EXECUTORS_H__
diff --git a/runtime/onert/core/src/exec/train/TrainableFnSequence.cc b/runtime/onert/core/src/exec/train/TrainableFnSequence.cc
new file mode 100644
index 000000000..084b3d708
--- /dev/null
+++ b/runtime/onert/core/src/exec/train/TrainableFnSequence.cc
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "exec/train/TrainableFnSequence.h"
+
+namespace onert
+{
+namespace exec
+{
+namespace train
+{
+
+void TrainableFnSequence::forward(bool training)
+{
+ for (const auto &function : _functions)
+ {
+ function->forward(training);
+ }
+}
+
+void TrainableFnSequence::backward(uint32_t training_step)
+{
+ for (auto it = _functions.rbegin(); it != _functions.rend(); ++it)
+ {
+ (*it)->backward();
+ }
+
+ for (const auto &applier : _appliers)
+ {
+ applier->applyGradient(training_step);
+ }
+}
+
+void TrainableFnSequence::append(std::unique_ptr<ITrainableFunction> &&function)
+{
+ _functions.push_back(std::move(function));
+}
+
+void TrainableFnSequence::append(std::unique_ptr<IGradientApplier> &&applier)
+{
+ _appliers.push_back(std::move(applier));
+}
+
+void TrainableFnSequence::iterate(const std::function<void(ITrainableFunction &)> &fn)
+{
+ for (const auto &func : _functions)
+ {
+ fn(*func);
+ }
+}
+
+} // namespace train
+} // namespace exec
+} // namespace onert
diff --git a/runtime/onert/core/src/exec/train/optimizer/OptimizerCode.cc b/runtime/onert/core/src/exec/train/optimizer/OptimizerCode.cc
new file mode 100644
index 000000000..72b581bf6
--- /dev/null
+++ b/runtime/onert/core/src/exec/train/optimizer/OptimizerCode.cc
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "exec/train/optimizer/OptimizerCode.h"
+
+#include <unordered_map>
+
+namespace onert
+{
+namespace exec
+{
+namespace train
+{
+namespace optimizer
+{
+
+std::string toString(OptimizerCode code)
+{
+ static const std::unordered_map<OptimizerCode, const char *> map{
+ {OptimizerCode::Invalid, "Invalid"},
+ {OptimizerCode::SGD, "SGD"},
+ {OptimizerCode::Adam, "Adam"}};
+ return map.at(code);
+}
+
+} // namespace optimizer
+} // namespace train
+} // namespace exec
+} // namespace onert
diff --git a/runtime/onert/core/src/exec/train/optimizer/OptimizerHelpers.h b/runtime/onert/core/src/exec/train/optimizer/OptimizerHelpers.h
new file mode 100644
index 000000000..66a08b50f
--- /dev/null
+++ b/runtime/onert/core/src/exec/train/optimizer/OptimizerHelpers.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_EXEC_TRAIN_OPTIMIZER_OPTIMIZER_HELPERS_H__
+#define __ONERT_EXEC_TRAIN_OPTIMIZER_OPTIMIZER_HELPERS_H__
+
+#include "backend/IPortableTensor.h"
+
+namespace onert
+{
+namespace exec
+{
+namespace train
+{
+namespace optimizer
+{
+
+template <typename T, typename L>
+void elementwise(const ir::Shape &shape, const backend::ITensor &src, backend::ITensor &dst,
+ const L &f)
+{
+ ShapeLoop(shape, [&](const ir::Coordinates &coords) {
+ const T src_val = *reinterpret_cast<const T *>(src.buffer() + src.calcOffset(coords));
+ T *dst_data = reinterpret_cast<T *>(dst.buffer() + dst.calcOffset(coords));
+ *dst_data = f(src_val, *dst_data);
+ });
+}
+
+} // namespace optimizer
+} // namespace train
+} // namespace exec
+} // namespace onert
+
+#endif // __ONERT_EXEC_TRAIN_OPTIMIZER_OPTIMIZER_HELPERS_H__
diff --git a/runtime/onert/core/src/exec/train/optimizer/SGD.cc b/runtime/onert/core/src/exec/train/optimizer/SGD.cc
new file mode 100644
index 000000000..abfbc1b4b
--- /dev/null
+++ b/runtime/onert/core/src/exec/train/optimizer/SGD.cc
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <exec/train/optimizer/SGD.h>
+
+#include "OptimizerHelpers.h"
+
+namespace onert
+{
+namespace exec
+{
+namespace train
+{
+namespace optimizer
+{
+
+double SGD::getLearningRate(uint32_t) const
+{
+ // TODO Use iteration, momentum, and nesterov
+ return _learning_rate;
+}
+
+void SGD::applyGradient(const UpdateFactors &factors) const
+{
+ const auto lr = getLearningRate(std::get<size_t>(factors));
+ const auto &grad_tensor = std::get<const backend::IPortableTensor &>(factors);
+ auto &trainable_tensor = std::get<backend::train::ITrainableTensor &>(factors);
+ assert(trainable_tensor.data_type() == grad_tensor.data_type());
+
+ const auto shape = trainable_tensor.getShape();
+ const auto &grad_shape = grad_tensor.get_info().shape();
+
+ // TODO Support for different shapes
+ if (shape != grad_shape)
+ {
+ throw std::runtime_error("SGD: Invalid gradient tensor");
+ }
+
+ switch (grad_tensor.data_type())
+ {
+ case ir::DataType::FLOAT32:
+ elementwise<float>(shape, grad_tensor, trainable_tensor,
+ [&](float src, float dst) -> float { return dst - src * lr; });
+ break;
+ default:
+ throw std::runtime_error("SGD: Not supported data type");
+ }
+}
+
+} // namespace optimizer
+} // namespace train
+} // namespace exec
+} // namespace onert
diff --git a/runtime/onert/core/src/ir/Graph.cc b/runtime/onert/core/src/ir/Graph.cc
index 28cf4137d..ef0f988fa 100644
--- a/runtime/onert/core/src/ir/Graph.cc
+++ b/runtime/onert/core/src/ir/Graph.cc
@@ -42,33 +42,33 @@ OperandIndex Graph::addOperand(OperandIndex index, std::unique_ptr<Operand> &&op
return _operands.push(std::move(operand), index);
}
-bool Graph::checkOperandsForOperation(const Operation &operation)
+bool Graph::checkOperandsForOperation(const IOperation &operation)
{
auto inputs = operation.getInputs() | ir::Remove::UNDEFINED | ir::Remove::DUPLICATED;
auto outputs = operation.getOutputs() | ir::Remove::UNDEFINED | ir::Remove::DUPLICATED;
- for (auto input : inputs)
+ for (auto &&input : inputs)
if (!operands().exist(input))
return false;
- for (auto input : outputs)
+ for (auto &&input : outputs)
if (!operands().exist(input))
return false;
return true;
}
-void Graph::linkOperandToOperation(OperationIndex index, const Operation &operation)
+void Graph::linkOperandToOperation(OperationIndex index, const IOperation &operation)
{
auto inputs = operation.getInputs() | ir::Remove::UNDEFINED | ir::Remove::DUPLICATED;
auto outputs = operation.getOutputs() | ir::Remove::UNDEFINED | ir::Remove::DUPLICATED;
- for (auto input : inputs)
+ for (auto &&input : inputs)
operands().at(input).insertUse(index);
- for (auto output : outputs)
+ for (auto &&output : outputs)
operands().at(output).setDef(index);
}
-OperationIndex Graph::addOperation(std::unique_ptr<Operation> &&operation)
+OperationIndex Graph::addOperation(std::unique_ptr<IOperation> &&operation)
{
- const Operation &op_ref = *operation;
+ const IOperation &op_ref = *operation;
if (!checkOperandsForOperation(op_ref))
return OperationIndex{};
auto ind = _operations.push(std::move(operation));
@@ -77,9 +77,9 @@ OperationIndex Graph::addOperation(std::unique_ptr<Operation> &&operation)
return ind;
}
-OperationIndex Graph::addOperation(OperationIndex index, std::unique_ptr<Operation> &&operation)
+OperationIndex Graph::addOperation(OperationIndex index, std::unique_ptr<IOperation> &&operation)
{
- const Operation &op_ref = *operation;
+ const IOperation &op_ref = *operation;
if (!checkOperandsForOperation(op_ref))
return OperationIndex{};
auto ind_gen = _operations.push(std::move(operation), index);
@@ -91,12 +91,35 @@ OperationIndex Graph::addOperation(OperationIndex index, std::unique_ptr<Operati
return index;
}
+OperationIndex Graph::replaceOperation(OperationIndex index,
+ std::unique_ptr<IOperation> &&operation)
+{
+ const IOperation &op_ref = *operation;
+ if (!checkOperandsForOperation(op_ref) || !_operations.exist(index))
+ return OperationIndex{};
+
+ // Check the new operation has the same inputs/outputs as the existing operation
+ const auto &old_op = _operations.at(index);
+ if (!(old_op.getInputs() == op_ref.getInputs() && old_op.getOutputs() == op_ref.getOutputs()))
+ {
+ return OperationIndex{};
+ }
+
+ return _operations.set(index, std::move(operation));
+}
+
void Graph::setOperandValue(const OperandIndex &ind, std::shared_ptr<Data> data)
{
assert(_operands.exist(ind));
_operands.at(ind).data(std::move(data));
}
+void Graph::changeShape(const OperandIndex &ind, const ir::Shape &new_shape)
+{
+ assert(_operands.exist(ind));
+ _operands.at(ind).info().shape(new_shape);
+}
+
void Graph::addInput(const OperandIndex &ind, const std::string &name)
{
if (!name.empty())
@@ -123,7 +146,7 @@ IOIndex Graph::getOutputIndex(const std::string &name) const
return (itr == _name_to_output.end()) ? IOIndex{} : itr->second;
}
-void Graph::verify(void)
+void Graph::verify(void) const
{
// Call graph verifications for the MODEL phase
{
@@ -144,14 +167,14 @@ void Graph::verify(void)
void Graph::initializeUseDef()
{
- operations().iterate([&](const OperationIndex &index, const Operation &node) -> void {
+ operations().iterate([&](const OperationIndex &index, const IOperation &node) -> void {
auto outputs = node.getOutputs();
- for (auto output : outputs | ir::Remove::UNDEFINED)
+ for (auto &&output : outputs | ir::Remove::UNDEFINED)
{
operands().at(output).setDef(index);
}
- for (auto input : node.getInputs() | ir::Remove::UNDEFINED)
+ for (auto &&input : node.getInputs() | ir::Remove::UNDEFINED)
{
operands().at(input).insertUse(index);
}
@@ -163,15 +186,15 @@ std::vector<ir::OperationIndex> Graph::topolSortOperations() const
std::vector<ir::OperationIndex> ret;
util::Set<ir::OperationIndex> unvisited;
operations().iterate(
- [&](const ir::OperationIndex &index, const ir::Operation &) { unvisited.add(index); });
+ [&](const ir::OperationIndex &index, const ir::IOperation &) { unvisited.add(index); });
- std::function<void(const ir::OperationIndex &, const ir::Operation &)> dfs =
- [&](const ir::OperationIndex &index, const ir::Operation &op) -> void {
+ std::function<void(const ir::OperationIndex &, const ir::IOperation &)> dfs =
+ [&](const ir::OperationIndex &index, const ir::IOperation &op) -> void {
if (!unvisited.contains(index))
return;
unvisited.remove(index);
- for (const auto output : op.getOutputs() | ir::Remove::DUPLICATED | ir::Remove::UNDEFINED)
+ for (const auto &output : op.getOutputs() | ir::Remove::DUPLICATED | ir::Remove::UNDEFINED)
{
const auto &operand = operands().at(output);
for (const auto &use : operand.getUses())
diff --git a/runtime/onert/core/src/ir/LayoutSet.cc b/runtime/onert/core/src/ir/LayoutSet.cc
index bd3f438ad..732460aa2 100644
--- a/runtime/onert/core/src/ir/LayoutSet.cc
+++ b/runtime/onert/core/src/ir/LayoutSet.cc
@@ -23,7 +23,7 @@ namespace ir
LayoutSet::LayoutSet(std::initializer_list<Layout> layouts)
{
- for (auto layout : layouts)
+ for (auto &&layout : layouts)
{
_set.insert(layout);
}
@@ -32,7 +32,7 @@ LayoutSet::LayoutSet(std::initializer_list<Layout> layouts)
LayoutSet LayoutSet::operator|(const LayoutSet &other) const
{
auto ret = *this;
- for (auto layout : other)
+ for (auto &&layout : other)
{
ret.add(layout);
}
@@ -42,7 +42,7 @@ LayoutSet LayoutSet::operator|(const LayoutSet &other) const
LayoutSet LayoutSet::operator&(const LayoutSet &other) const
{
LayoutSet ret;
- for (auto layout : other)
+ for (auto &&layout : other)
{
if (contains(layout))
{
@@ -55,7 +55,7 @@ LayoutSet LayoutSet::operator&(const LayoutSet &other) const
LayoutSet LayoutSet::operator-(const LayoutSet &other) const
{
auto ret = *this;
- for (auto layout : other)
+ for (auto &&layout : other)
{
ret.remove(layout);
}
diff --git a/runtime/onert/core/src/ir/LayoutSet.h b/runtime/onert/core/src/ir/LayoutSet.h
index 6ce4e38c6..be077f2f0 100644
--- a/runtime/onert/core/src/ir/LayoutSet.h
+++ b/runtime/onert/core/src/ir/LayoutSet.h
@@ -17,6 +17,7 @@
#ifndef __ONERT_IR_LAYOUT_SET_H__
#define __ONERT_IR_LAYOUT_SET_H__
+#include <cstdint>
#include <initializer_list>
#include <unordered_set>
diff --git a/runtime/onert/core/src/ir/OperandIndexSequence.cc b/runtime/onert/core/src/ir/OperandIndexSequence.cc
index b092f5cee..a15b6d0d6 100644
--- a/runtime/onert/core/src/ir/OperandIndexSequence.cc
+++ b/runtime/onert/core/src/ir/OperandIndexSequence.cc
@@ -31,7 +31,7 @@ OperandIndexSequence::OperandIndexSequence(std::initializer_list<OperandIndex> l
OperandIndexSequence::OperandIndexSequence(std::initializer_list<int32_t> list)
{
- for (auto val : list)
+ for (auto &&val : list)
{
_vec.emplace_back(static_cast<uint32_t>(val));
}
@@ -39,7 +39,7 @@ OperandIndexSequence::OperandIndexSequence(std::initializer_list<int32_t> list)
OperandIndexSequence::OperandIndexSequence(std::initializer_list<uint32_t> list)
{
- for (auto val : list)
+ for (auto &&val : list)
{
_vec.emplace_back(val);
}
@@ -55,6 +55,11 @@ void OperandIndexSequence::replace(const OperandIndex &from, const OperandIndex
std::replace(_vec.begin(), _vec.end(), from, to);
}
+bool OperandIndexSequence::operator==(const OperandIndexSequence &other) const
+{
+ return _vec == other._vec;
+}
+
OperandIndexSequence OperandIndexSequence::operator+(const OperandIndexSequence &other) const
{
OperandIndexSequence ret = *this;
diff --git a/runtime/onert/core/src/ir/OperationCloner.cc b/runtime/onert/core/src/ir/OperationCloner.cc
index c06315814..64e1cc807 100644
--- a/runtime/onert/core/src/ir/OperationCloner.cc
+++ b/runtime/onert/core/src/ir/OperationCloner.cc
@@ -57,7 +57,7 @@ std::unique_ptr<Operation> OperationCloner::releaseClone()
} // namespace
-std::unique_ptr<Operation> clone(const Operation &operation)
+std::unique_ptr<Operation> clone(const IOperation &operation)
{
OperationCloner cloner;
operation.accept(cloner);
diff --git a/runtime/onert/core/src/ir/OperationCloner.h b/runtime/onert/core/src/ir/OperationCloner.h
index 6424549e9..49297a05c 100644
--- a/runtime/onert/core/src/ir/OperationCloner.h
+++ b/runtime/onert/core/src/ir/OperationCloner.h
@@ -26,7 +26,7 @@ namespace onert
namespace ir
{
-std::unique_ptr<Operation> clone(const Operation &operation);
+std::unique_ptr<Operation> clone(const IOperation &operation);
} // namespace ir
} // namespace onert
diff --git a/runtime/onert/core/src/ir/OperationDumper.cc b/runtime/onert/core/src/ir/OperationDumper.cc
index 0b596ff13..5e6d700f3 100644
--- a/runtime/onert/core/src/ir/OperationDumper.cc
+++ b/runtime/onert/core/src/ir/OperationDumper.cc
@@ -202,6 +202,14 @@ void OperationDumper::visit(const L2Normalization &node) { dumpOpGeneric(node);
void OperationDumper::visit(const LocalResponseNormalization &node) { dumpOpGeneric(node); }
+void OperationDumper::visit(const Loss &node)
+{
+ VERBOSE(LIR) << "* " << node.name() << std::endl;
+ VERBOSE(LIR) << " - Inputs : Prediction(" << node.getInputs().at(Loss::Input::Y_PRED) << ") True("
+ << node.getInputs().at(Loss::Input::Y_TRUE) << ")" << std::endl;
+ VERBOSE(LIR) << " - Outputs : Output(" << node.getOutputs().at(0) << ")" << std::endl;
+}
+
void OperationDumper::visit(const LSTM &node)
{
VERBOSE(LIR) << "* " << node.name() << std::endl;
diff --git a/runtime/onert/core/src/ir/OperationDumper.h b/runtime/onert/core/src/ir/OperationDumper.h
index fe18307b9..99bf869d5 100644
--- a/runtime/onert/core/src/ir/OperationDumper.h
+++ b/runtime/onert/core/src/ir/OperationDumper.h
@@ -55,6 +55,7 @@ public:
void visit(const operation::InstanceNorm &) override;
void visit(const operation::L2Normalization &) override;
void visit(const operation::LocalResponseNormalization &) override;
+ void visit(const operation::Loss &node) override;
void visit(const operation::LSTM &) override;
void visit(const operation::Pack &) override;
void visit(const operation::Pad &) override;
diff --git a/runtime/onert/core/src/ir/OperationValidator.cc b/runtime/onert/core/src/ir/OperationValidator.cc
index 094dbc0d5..cf7323d77 100644
--- a/runtime/onert/core/src/ir/OperationValidator.cc
+++ b/runtime/onert/core/src/ir/OperationValidator.cc
@@ -38,7 +38,7 @@ OperationValidator::OperationValidator(const Graph &graph)
void OperationValidator::operator()()
{
- _operations.iterate([&](const OperationIndex &, const Operation &node) { node.accept(*this); });
+ _operations.iterate([&](const OperationIndex &, const IOperation &node) { node.accept(*this); });
}
DataType OperationValidator::operandType(const OperandIndex &idx)
@@ -75,7 +75,7 @@ bool OperationValidator::isValidType(const OperandIndex &idx, const DataType &ty
bool OperationValidator::isValidType(const OperandIndex &idx,
std::initializer_list<DataType> valid_types)
{
- for (auto type_to_check : valid_types)
+ for (auto &&type_to_check : valid_types)
{
if (isValidType(idx, type_to_check))
{
@@ -163,7 +163,7 @@ void OperationValidator::visit(const operation::Concat &node)
{
const auto output_index{node.getOutputs().at(0)};
- for (auto input_index : node.getInputs())
+ for (auto &&input_index : node.getInputs())
{
OP_REQUIRES(isSameType(input_index, output_index));
diff --git a/runtime/onert/core/src/ir/Operations.cc b/runtime/onert/core/src/ir/Operations.cc
index e7e0c88cf..1b4691f58 100644
--- a/runtime/onert/core/src/ir/Operations.cc
+++ b/runtime/onert/core/src/ir/Operations.cc
@@ -26,7 +26,7 @@ namespace ir
Operations::Operations(const Operations &obj)
{
obj.iterate(
- [&](const OperationIndex &index, const Operation &op) { _objects.emplace(index, clone(op)); });
+ [&](const OperationIndex &index, const IOperation &op) { _objects.emplace(index, clone(op)); });
_next_index = obj._next_index;
}
diff --git a/runtime/onert/core/src/ir/operation/Loss.cc b/runtime/onert/core/src/ir/operation/Loss.cc
new file mode 100644
index 000000000..fa3520b2c
--- /dev/null
+++ b/runtime/onert/core/src/ir/operation/Loss.cc
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ir/operation/Loss.h"
+#include "ir/OperationVisitor.h"
+
+#include <unordered_map>
+
+namespace onert
+{
+namespace ir
+{
+namespace operation
+{
+
+void Loss::accept(OperationVisitor &v) const { v.visit(*this); }
+
+Loss::Loss(const OperandIndexSequence &inputs, const OperandIndexSequence &outputs,
+ const Param &param)
+ : Operation{OperandConstraint::createAtLeast(2u), inputs, outputs}, _param{param}
+{
+ if (param.op_type == Type::CATEGORICAL_CROSSENTROPY)
+ {
+ assert(inputs.size() == 2 && "CategoricalCrossentropy Loss has 2 inputs");
+ }
+}
+
+std::string Loss::name() const
+{
+ using LossType = onert::ir::operation::Loss::Type;
+ static const std::unordered_map<Type, std::string> name_map{
+ {LossType::MEAN_SQUARED_ERROR, "MeanSquaredError Loss"},
+ {LossType::CATEGORICAL_CROSSENTROPY, "CategoricalCrossentropy Loss"}};
+ return name_map.at(_param.op_type);
+}
+
+} // namespace operation
+} // namespace ir
+} // namespace onert
diff --git a/runtime/onert/core/src/ir/train/TrainableGraph.cc b/runtime/onert/core/src/ir/train/TrainableGraph.cc
new file mode 100644
index 000000000..781f04956
--- /dev/null
+++ b/runtime/onert/core/src/ir/train/TrainableGraph.cc
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ir/train/TrainableGraph.h"
+#include "util/Utils.h"
+
+#include <algorithm>
+#include <misc/polymorphic_downcast.h>
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+
+TrainableGraph::TrainableGraph() : _graph{} {}
+
+TrainableGraph::TrainableGraph(const TrainableGraph &tgraph)
+ : _graph{tgraph._graph}, _derivatives{tgraph._derivatives}, _losses{tgraph._losses}
+{
+ tgraph.operations().iterate(
+ [&](const onert::ir::OperationIndex &index, const onert::ir::IOperation &op) {
+ replaceOperation(index, dynamic_cast<const ITrainableOperation &>(op).clone());
+ });
+}
+
+TrainableGraph::TrainableGraph(const Graph &graph) : _graph{graph} {}
+
+OperandIndex TrainableGraph::addOperand(const Shape &shape, const TypeInfo &type)
+{
+ return _graph.addOperand(shape, type);
+}
+
+OperandIndex TrainableGraph::addOperand(OperandIndex index, std::unique_ptr<Operand> &&operand)
+{
+ return _graph.addOperand(index, std::move(operand));
+}
+
+OperationIndex TrainableGraph::addOperation(std::unique_ptr<ITrainableOperation> &&operation)
+{
+ return _graph.addOperation(std::move(operation));
+}
+
+OperationIndex TrainableGraph::replaceOperation(OperationIndex index,
+ std::unique_ptr<ITrainableOperation> &&operation)
+{
+ return _graph.replaceOperation(index, std::move(operation));
+}
+
+OperandIndex TrainableGraph::addDerivative(OperandIndex index,
+ std::unique_ptr<Operand> &&derivative)
+{
+ return _derivatives.push(std::move(derivative), index);
+}
+
+IOIndex TrainableGraph::getInputIndex(const std::string &name) const
+{
+ return _graph.getInputIndex(name);
+}
+
+IOIndex TrainableGraph::getOutputIndex(const std::string &name) const
+{
+ return _graph.getOutputIndex(name);
+}
+
+void TrainableGraph::changeShape(const OperandIndex &index, const ir::Shape &new_shape)
+{
+ _graph.changeShape(index, new_shape);
+}
+
+void TrainableGraph::changeDerivativeShape(const OperandIndex &index, const ir::Shape &new_shape)
+{
+ assert(_derivatives.exist(index));
+ _derivatives.at(index).info().shape(new_shape);
+}
+
+void TrainableGraph::addInput(const OperandIndex &ind, const std::string &name)
+{
+ _graph.addInput(ind, name);
+}
+
+void TrainableGraph::addOutput(const OperandIndex &ind, const std::string &name)
+{
+ _graph.addOutput(ind, name);
+}
+
+void TrainableGraph::verify(void) const
+{
+ _graph.verify();
+
+ operations().iterate([](const onert::ir::OperationIndex &, const onert::ir::IOperation &op) {
+ try
+ {
+ UNUSED_RELEASE(dynamic_cast<const onert::ir::train::ITrainableOperation &>(op));
+ }
+ catch (const std::bad_cast &)
+ {
+ std::runtime_error("TrainableGraph: " + op.name() + " is not a trainable operation");
+ }
+ });
+}
+
+void TrainableGraph::removeOperand(const OperandIndex &ind) { _graph.removeOperand(ind); }
+
+void TrainableGraph::setLayout(Layout layout) { _graph.setLayout(layout); }
+
+const ITrainableOperation &TrainableGraph::operation(OperationIndex index) const
+{
+ // NOTE Virtual inherited objects cannot be static_casted.
+ return dynamic_cast<const ITrainableOperation &>(_graph.operations().at(index));
+}
+
+std::vector<ir::OperationIndex> TrainableGraph::topolSortOperations() const
+{
+ return _graph.topolSortOperations();
+}
+
+void TrainableGraph::addLoss(const OperandIndex &loss_ind, const IOIndex &pred_ioind)
+{
+ _losses.emplace(pred_ioind, loss_ind);
+}
+
+OperandIndex TrainableGraph::getLossIndex(const IOIndex &pred_ioind) const
+{
+ auto itr = _losses.find(pred_ioind);
+ return (itr == _losses.end()) ? OperandIndex{} : itr->second;
+}
+
+} // namespace train
+} // namespace ir
+} // namespace onert
diff --git a/runtime/onert/core/src/ir/train/operation/Conv2D.cc b/runtime/onert/core/src/ir/train/operation/Conv2D.cc
new file mode 100644
index 000000000..923861ae3
--- /dev/null
+++ b/runtime/onert/core/src/ir/train/operation/Conv2D.cc
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ir/train/operation/Conv2D.h"
+
+#include "ir/OperationVisitor.h"
+#include "ir/train/TrainableOperationVisitor.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+std::unique_ptr<ITrainableOperation> Conv2D::clone() const
+{
+ return std::make_unique<Conv2D>(*this);
+}
+
+void Conv2D::accept(OperationVisitor &v) const { v.visit(*this); }
+
+void Conv2D::accept(TrainableOperationVisitor &v) const { v.visit(*this); }
+
+Conv2D::Conv2D(const OperationType &operation)
+ : OperationType{operation.getInputs(), operation.getOutputs(), operation.param()}
+{
+ // DO NOTHING
+}
+
+} // namespace operation
+} // namespace train
+} // namespace ir
+} // namespace onert
diff --git a/runtime/onert/core/src/ir/train/operation/ElementwiseActivation.cc b/runtime/onert/core/src/ir/train/operation/ElementwiseActivation.cc
new file mode 100644
index 000000000..1dae3f674
--- /dev/null
+++ b/runtime/onert/core/src/ir/train/operation/ElementwiseActivation.cc
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ir/train/operation/ElementwiseActivation.h"
+
+#include "ir/OperationVisitor.h"
+#include "ir/train/TrainableOperationVisitor.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+std::unique_ptr<ITrainableOperation> ElementwiseActivation::clone() const
+{
+ return std::make_unique<ElementwiseActivation>(*this);
+}
+
+void ElementwiseActivation::accept(OperationVisitor &v) const { v.visit(*this); }
+
+void ElementwiseActivation::accept(TrainableOperationVisitor &v) const { v.visit(*this); }
+
+ElementwiseActivation::ElementwiseActivation(const OperationType &operation)
+ : OperationType{operation.getInputs(), operation.getOutputs(), operation.param()}
+{
+ // DO NOTHING
+}
+
+} // namespace operation
+} // namespace train
+} // namespace ir
+} // namespace onert
diff --git a/runtime/onert/core/src/ir/train/operation/FullyConnected.cc b/runtime/onert/core/src/ir/train/operation/FullyConnected.cc
new file mode 100644
index 000000000..a26f7c489
--- /dev/null
+++ b/runtime/onert/core/src/ir/train/operation/FullyConnected.cc
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ir/train/operation/FullyConnected.h"
+
+#include "ir/OperationVisitor.h"
+#include "ir/train/TrainableOperationVisitor.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+std::unique_ptr<ITrainableOperation> FullyConnected::clone() const
+{
+ return std::make_unique<FullyConnected>(*this);
+}
+
+void FullyConnected::accept(OperationVisitor &v) const { v.visit(*this); }
+
+void FullyConnected::accept(TrainableOperationVisitor &v) const { v.visit(*this); }
+
+FullyConnected::FullyConnected(const OperationType &operation)
+ : OperationType{operation.getInputs(), operation.getOutputs(), operation.param()}
+{
+ // DO NOTHING
+}
+
+} // namespace operation
+} // namespace train
+} // namespace ir
+} // namespace onert
diff --git a/runtime/onert/core/src/ir/train/operation/Loss.cc b/runtime/onert/core/src/ir/train/operation/Loss.cc
new file mode 100644
index 000000000..abd79929b
--- /dev/null
+++ b/runtime/onert/core/src/ir/train/operation/Loss.cc
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ir/train/operation/Loss.h"
+
+#include "ir/OperationVisitor.h"
+#include "ir/train/TrainableOperationVisitor.h"
+
+#include <misc/polymorphic_downcast.h>
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+std::unique_ptr<ITrainableOperation> Loss::clone() const { return std::make_unique<Loss>(*this); }
+
+void Loss::accept(OperationVisitor &v) const { v.visit(*this); }
+
+void Loss::accept(TrainableOperationVisitor &v) const { v.visit(*this); }
+
+Loss::Loss(const OperationType &operation)
+ : OperationType{operation.getInputs(), operation.getOutputs(), operation.param()}
+{
+ // DO NOTHING
+}
+
+} // namespace operation
+} // namespace train
+} // namespace ir
+} // namespace onert
diff --git a/runtime/onert/core/src/ir/train/operation/Permute.cc b/runtime/onert/core/src/ir/train/operation/Permute.cc
new file mode 100644
index 000000000..adc23aa49
--- /dev/null
+++ b/runtime/onert/core/src/ir/train/operation/Permute.cc
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ir/train/operation/Permute.h"
+
+#include "ir/OperationVisitor.h"
+#include "ir/train/TrainableOperationVisitor.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+std::unique_ptr<ITrainableOperation> Permute::clone() const
+{
+ return std::make_unique<Permute>(*this);
+}
+
+void Permute::accept(OperationVisitor &v) const { v.visit(*this); }
+
+void Permute::accept(TrainableOperationVisitor &v) const { v.visit(*this); }
+
+Permute::Permute(const OperationType &operation)
+ : OperationType{operation.getInputs().at(0), operation.getOutputs().at(0),
+ operation.getPermuteType()}
+{
+ // DO NOTHING
+}
+
+} // namespace operation
+} // namespace train
+} // namespace ir
+} // namespace onert
diff --git a/runtime/onert/core/src/ir/train/operation/Pool2D.cc b/runtime/onert/core/src/ir/train/operation/Pool2D.cc
new file mode 100644
index 000000000..021574f19
--- /dev/null
+++ b/runtime/onert/core/src/ir/train/operation/Pool2D.cc
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ir/train/operation/Pool2D.h"
+
+#include "ir/OperationVisitor.h"
+#include "ir/train/TrainableOperationVisitor.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+std::unique_ptr<ITrainableOperation> Pool2D::clone() const
+{
+ return std::make_unique<Pool2D>(*this);
+}
+
+void Pool2D::accept(OperationVisitor &v) const { v.visit(*this); }
+
+void Pool2D::accept(TrainableOperationVisitor &v) const { v.visit(*this); }
+
+Pool2D::Pool2D(const OperationType &operation)
+ : OperationType{operation.getInputs(), operation.getOutputs(), operation.param()}
+{
+ // DO NOTHING
+}
+
+} // namespace operation
+} // namespace train
+} // namespace ir
+} // namespace onert
diff --git a/runtime/onert/core/src/ir/train/operation/Reshape.cc b/runtime/onert/core/src/ir/train/operation/Reshape.cc
new file mode 100644
index 000000000..c76158607
--- /dev/null
+++ b/runtime/onert/core/src/ir/train/operation/Reshape.cc
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ir/train/operation/Reshape.h"
+
+#include "ir/OperationVisitor.h"
+#include "ir/train/TrainableOperationVisitor.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+std::unique_ptr<ITrainableOperation> Reshape::clone() const
+{
+ return std::make_unique<Reshape>(*this);
+}
+
+void Reshape::accept(OperationVisitor &v) const { v.visit(*this); }
+
+void Reshape::accept(TrainableOperationVisitor &v) const { v.visit(*this); }
+
+Reshape::Reshape(const OperationType &operation)
+ : OperationType{operation.getInputs(), operation.getOutputs(), operation.param()}
+{
+ // DO NOTHING
+}
+
+} // namespace operation
+} // namespace train
+} // namespace ir
+} // namespace onert
diff --git a/runtime/onert/core/src/ir/train/operation/Softmax.cc b/runtime/onert/core/src/ir/train/operation/Softmax.cc
new file mode 100644
index 000000000..dbd403879
--- /dev/null
+++ b/runtime/onert/core/src/ir/train/operation/Softmax.cc
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ir/train/operation/Softmax.h"
+
+#include "ir/OperationVisitor.h"
+#include "ir/train/TrainableOperationVisitor.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+std::unique_ptr<ITrainableOperation> Softmax::clone() const
+{
+ return std::make_unique<Softmax>(*this);
+}
+
+void Softmax::accept(OperationVisitor &v) const { v.visit(*this); }
+
+void Softmax::accept(TrainableOperationVisitor &v) const { v.visit(*this); }
+
+Softmax::Softmax(const OperationType &operation)
+ : OperationType{operation.getInputs(), operation.getOutputs(), operation.param()}
+{
+ // DO NOTHING
+}
+
+} // namespace operation
+} // namespace train
+} // namespace ir
+} // namespace onert
diff --git a/runtime/onert/core/src/ir/verifier/Verifier.cc b/runtime/onert/core/src/ir/verifier/Verifier.cc
index 25a82d5a2..6260d29ff 100644
--- a/runtime/onert/core/src/ir/verifier/Verifier.cc
+++ b/runtime/onert/core/src/ir/verifier/Verifier.cc
@@ -39,11 +39,11 @@ bool DAGChecker::verify(const Graph &graph) const noexcept
OperationIndexMap<bool> visited;
operations.iterate(
- [&](const OperationIndex &index, const Operation &) { visited[index] = false; });
+ [&](const OperationIndex &index, const IOperation &) { visited[index] = false; });
OperationIndexMap<bool> on_stack = visited; // Copy from visited
- std::function<void(const OperationIndex &index, const Operation &)> dfs_recursive =
- [&](const OperationIndex &index, const Operation &node) -> void {
+ std::function<void(const OperationIndex &index, const IOperation &)> dfs_recursive =
+ [&](const OperationIndex &index, const IOperation &node) -> void {
if (on_stack[index])
cyclic = true;
if (visited[index])
@@ -51,7 +51,7 @@ bool DAGChecker::verify(const Graph &graph) const noexcept
visited[index] = true;
on_stack[index] = true;
- for (auto output : node.getOutputs() | Remove::DUPLICATED | Remove::UNDEFINED)
+ for (auto &&output : node.getOutputs() | Remove::DUPLICATED | Remove::UNDEFINED)
{
const auto &operand = graph.operands().at(output);
for (const auto &use : operand.getUses())
@@ -76,8 +76,8 @@ bool EdgeChecker::verify(const Graph &graph) const noexcept
{
auto &operations = graph.operations();
uint32_t errors = 0;
- operations.iterate([&](const OperationIndex &index, const Operation &node) {
- for (auto operand_index : node.getInputs() | ir::Remove::UNDEFINED)
+ operations.iterate([&](const OperationIndex &index, const IOperation &node) {
+ for (auto &&operand_index : node.getInputs() | ir::Remove::UNDEFINED)
{
try
{
@@ -98,7 +98,7 @@ bool EdgeChecker::verify(const Graph &graph) const noexcept
errors += 1;
}
}
- for (auto operand_index : node.getOutputs() | ir::Remove::UNDEFINED)
+ for (auto &&operand_index : node.getOutputs() | ir::Remove::UNDEFINED)
{
try
{
@@ -127,7 +127,7 @@ bool EdgeChecker::verify(const Graph &graph) const noexcept
bool InputOutputChecker::verify(const Graph &graph) const noexcept
{
- for (auto operand_ind :
+ for (auto &&operand_ind :
(graph.getInputs() + graph.getOutputs()) | Remove::DUPLICATED | Remove::UNDEFINED)
{
if (!graph.operands().exist(operand_ind))
diff --git a/runtime/onert/core/src/odc/QuantizeManager.cc b/runtime/onert/core/src/odc/QuantizeManager.cc
new file mode 100644
index 000000000..71572a7e0
--- /dev/null
+++ b/runtime/onert/core/src/odc/QuantizeManager.cc
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "QuantizerLoader.h"
+#include "odc/QuantizeManager.h"
+
+#include <iostream>
+#include <mutex>
+
+namespace onert
+{
+namespace odc
+{
+
+bool QuantizeManager::quantize()
+{
+ // Compile function is thread-unsafe
+ static std::mutex lock;
+ std::lock_guard<std::mutex> guard(lock);
+
+ if (_export_model_path.empty())
+ throw std::runtime_error("Export model path is not set");
+
+ auto &quantize_loader = QuantizerLoader::instance();
+ if (quantize_loader.loadLibrary() != 0)
+ return false;
+
+ auto quantizer = quantize_loader.get();
+ auto result = quantizer->quantize(_model_path.c_str(), _export_model_path.c_str(), _is_q16);
+
+ // TODO Unload quantize library to reduce memory usage
+
+ return (result == 0);
+}
+
+} // namespace odc
+} // namespace onert
diff --git a/runtime/onert/core/src/odc/QuantizeManager.test.cc b/runtime/onert/core/src/odc/QuantizeManager.test.cc
new file mode 100644
index 000000000..4e155a6ef
--- /dev/null
+++ b/runtime/onert/core/src/odc/QuantizeManager.test.cc
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "odc/QuantizeManager.h"
+
+#include <gtest/gtest.h>
+
+using namespace onert::odc;
+
+// Test export model path is not set
+TEST(odc_QuantizeManager, neg_export_model_path)
+{
+ QuantizeManager manager("model_path");
+ ASSERT_THROW(manager.quantize(), std::runtime_error);
+}
+
+// Test invalid model path
+TEST(odc_QuantizeManager, neg_invalid_model_path)
+{
+ QuantizeManager manager("invalid_model_path.circle");
+ manager.exportModelPath("export_model_path.circle");
+ ASSERT_EQ(manager.quantize(), false);
+}
diff --git a/runtime/onert/core/src/odc/QuantizerLoader.cc b/runtime/onert/core/src/odc/QuantizerLoader.cc
new file mode 100644
index 000000000..8a972e97e
--- /dev/null
+++ b/runtime/onert/core/src/odc/QuantizerLoader.cc
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "QuantizerLoader.h"
+
+#include <dlfcn.h>
+#include <iostream>
+#include <string>
+
+static const char *SHARED_LIB_EXT =
+#if defined(__APPLE__) && defined(__MACH__)
+ ".dylib";
+#else
+ ".so";
+#endif
+
+namespace onert
+{
+namespace odc
+{
+
+QuantizerLoader &QuantizerLoader::instance()
+{
+ static QuantizerLoader singleton;
+ return singleton;
+}
+
+int32_t QuantizerLoader::loadLibrary()
+{
+ if (get() != nullptr)
+ return 0;
+
+ const std::string quantize_so = std::string("libonert_odc") + SHARED_LIB_EXT;
+ void *handle = dlopen(quantize_so.c_str(), RTLD_LAZY | RTLD_LOCAL);
+ auto dlerror_msg = dlerror();
+
+ if (handle == nullptr)
+ {
+ std::cerr << "Failed to load " << quantize_so << std::endl;
+ std::cerr << dlerror_msg << std::endl;
+ return 1;
+ }
+
+ {
+ const char *factory_name = "create_quantizer";
+ auto factory = (factory_t)dlsym(handle, factory_name);
+ dlerror_msg = dlerror();
+
+ if (factory == nullptr)
+ {
+ std::cerr << "QuantizerLoader: unable to find function " << factory_name << dlerror_msg
+ << std::endl;
+ dlclose(handle);
+ return 1;
+ }
+
+ auto destroyer = (quantizer_destory_t)dlsym(handle, "destroy_quantizer");
+ _quantizer = std::unique_ptr<IQuantizer, quantizer_destory_t>(factory(), destroyer);
+
+ if (_quantizer == nullptr)
+ {
+ std::cerr << "QuantizerLoader: unable to create quantizer" << std::endl;
+ dlclose(handle);
+ return 1;
+ }
+ }
+
+ // Save quantize library handle (avoid warning by handle lost without dlclose())
+ // clang-format off
+ _dlhandle = std::unique_ptr<void, dlhandle_destroy_t>{handle, [filename = quantize_so](void *h) {
+ if (dlclose(h) != 0)
+ std::cerr << "Failed to unload backend " << filename << std::endl;
+ }};
+ // clang-format on
+
+ return 0;
+}
+
+int32_t QuantizerLoader::unloadLibrary()
+{
+ if (get() == nullptr)
+ return 0;
+
+ _quantizer.reset(nullptr);
+ _dlhandle.reset(nullptr);
+
+ return 0;
+}
+
+} // namespace odc
+} // namespace onert
diff --git a/runtime/onert/core/src/odc/QuantizerLoader.h b/runtime/onert/core/src/odc/QuantizerLoader.h
new file mode 100644
index 000000000..36a9f2996
--- /dev/null
+++ b/runtime/onert/core/src/odc/QuantizerLoader.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_ODC_QUANTIZER_LOADER_H__
+#define __ONERT_ODC_QUANTIZER_LOADER_H__
+
+#include "odc/IQuantizer.h"
+
+#include <functional>
+#include <memory>
+
+namespace onert
+{
+namespace odc
+{
+
+/**
+ * @brief Class to manage loading and unloading of dynamic library containing
+ * implementation of IQuantizer interface
+ */
+class QuantizerLoader
+{
+public:
+ /**
+ * @brief Typedef for function pointer to destroy loaded library handle
+ */
+ using dlhandle_destroy_t = std::function<void(void *)>;
+ /**
+ * @brief Typedef for function pointer to create instance of IQuantizer
+ */
+ using factory_t = IQuantizer *(*)();
+ /**
+ * @brief Typedef for function pointer to destroy instance of IQuantizer
+ */
+ using quantizer_destory_t = void (*)(IQuantizer *);
+
+ /**
+ * @brief Get singleton instance of QuantizerLoader
+ * @return Reference to singleton instance of QuantizerLoader
+ */
+ static QuantizerLoader &instance();
+
+private:
+ // Cannot create instance of QuantizerLoader outside of this class
+ QuantizerLoader() = default;
+ QuantizerLoader(QuantizerLoader const &) = delete;
+ QuantizerLoader &operator=(QuantizerLoader const &) = delete;
+ ~QuantizerLoader() = default;
+
+public:
+ /**
+ * @brief Load dynamic library containing implementation of IQuantizer
+ * @return 0 if success, otherwise errno value
+ */
+ int32_t loadLibrary();
+ /**
+ * @brief Unload dynamic library containing implementation of IQuantizer
+ * @return 0 if success, otherwise errno value
+ */
+ int32_t unloadLibrary();
+ /**
+ * @brief Get instance of IQuantizer created through factory method
+ * @return Pointer to instance of IQuantizer
+ */
+ IQuantizer *get() const { return _quantizer.get(); }
+
+private:
+ // Note: Keep handle to avoid svace warning of "handle lost without dlclose()"
+ std::unique_ptr<void, dlhandle_destroy_t> _dlhandle;
+ std::unique_ptr<IQuantizer, quantizer_destory_t> _quantizer{nullptr, nullptr};
+};
+
+} // namespace odc
+} // namespace onert
+
+#endif // __ONERT_ODC_QUANTIZER_LOADER_H__
diff --git a/runtime/onert/core/src/odc/QuantizerLoader.test.cc b/runtime/onert/core/src/odc/QuantizerLoader.test.cc
new file mode 100644
index 000000000..112e65b27
--- /dev/null
+++ b/runtime/onert/core/src/odc/QuantizerLoader.test.cc
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "QuantizerLoader.h"
+
+#include <gtest/gtest.h>
+
+using namespace onert::odc;
+
+// Test QuantizerLoader singleton
+TEST(odc_QuantizerLoader, singleton)
+{
+ QuantizerLoader &loader1 = QuantizerLoader::instance();
+ QuantizerLoader &loader2 = QuantizerLoader::instance();
+ ASSERT_EQ(&loader1, &loader2);
+}
+
+// Test load quantizer library
+TEST(odc_QuantizerLoader, load)
+{
+ QuantizerLoader &loader = QuantizerLoader::instance();
+ // Unload because it may be loaded on previous tests
+ ASSERT_EQ(loader.unloadLibrary(), 0);
+
+ if (loader.loadLibrary() == 0)
+ {
+ // Load twice to check if it is thread-safe
+ ASSERT_EQ(loader.loadLibrary(), 0);
+ }
+}
+
+// Get quantizer function without loading quantizer library
+TEST(odc_QuantizerLoader, neg_get)
+{
+ QuantizerLoader &loader = QuantizerLoader::instance();
+ // Unload because it may be loaded on previous tests
+ ASSERT_EQ(loader.unloadLibrary(), 0);
+ ASSERT_EQ(loader.get(), nullptr);
+}
+
+// Check quantizer function pointer when QuantizerLoader is unloaded
+TEST(odc_QuantizerLoader, neg_unload)
+{
+ QuantizerLoader &loader = QuantizerLoader::instance();
+ if (loader.loadLibrary() == 0)
+ ASSERT_NE(loader.get(), nullptr);
+
+ ASSERT_EQ(loader.unloadLibrary(), 0);
+ ASSERT_EQ(loader.get(), nullptr);
+}
diff --git a/runtime/onert/core/src/util/MDTableEventWriter.cc b/runtime/onert/core/src/util/MDTableEventWriter.cc
index 13dab5b77..e7d90eec4 100644
--- a/runtime/onert/core/src/util/MDTableEventWriter.cc
+++ b/runtime/onert/core/src/util/MDTableEventWriter.cc
@@ -124,7 +124,7 @@ struct Graph : public MDContent
void setOperations(const std::map<std::string, Operation> &name_to_op)
{
uint64_t graph_latency = end_ts - begin_ts;
- for (auto it : name_to_op)
+ for (auto &&it : name_to_op)
{
auto op = it.second;
op.graph_latency = graph_latency;
@@ -172,7 +172,7 @@ struct Graph : public MDContent
writeMDTableRow(os, op_headers_line);
// Operation's contents
- for (auto op : ops)
+ for (auto &&op : ops)
{
op.write(os);
}
diff --git a/runtime/onert/frontend/base_loader/include/base_loader.h b/runtime/onert/frontend/base_loader/include/base_loader.h
index 878a594cc..a6b1fb4a1 100644
--- a/runtime/onert/frontend/base_loader/include/base_loader.h
+++ b/runtime/onert/frontend/base_loader/include/base_loader.h
@@ -513,11 +513,12 @@ void BaseLoader<LoaderDomain>::loadSparsity(const Tensor *tensor, ir::TypeInfo &
if (src_metadata->array_segments() == nullptr || src_metadata->array_indices() == nullptr)
return false;
bool status = true;
+ /* `onert` inernally uses uint16 type regardless of the value of
+ the array_segments_type and array_indices_type */
switch (src_metadata->array_segments_type())
{
case SparseIndexVector::SparseIndexVector_Int32Vector:
- status = Copy(src_metadata->array_segments_as_Int32Vector(), w1_segments);
- break;
+ throw std::runtime_error("sparse tensor with int32 segment type is not supported");
case SparseIndexVector::SparseIndexVector_Uint16Vector:
status = Copy(src_metadata->array_segments_as_Uint16Vector(), w1_segments);
break;
@@ -532,7 +533,7 @@ void BaseLoader<LoaderDomain>::loadSparsity(const Tensor *tensor, ir::TypeInfo &
switch (src_metadata->array_indices_type())
{
case SparseIndexVector::SparseIndexVector_Int32Vector:
- return Copy(src_metadata->array_indices_as_Int32Vector(), w1_indices);
+ throw std::runtime_error("sparse tensor with int32 indices type is not supported");
case SparseIndexVector::SparseIndexVector_Uint16Vector:
return Copy(src_metadata->array_indices_as_Uint16Vector(), w1_indices);
case SparseIndexVector::SparseIndexVector_Uint8Vector:
@@ -650,7 +651,19 @@ void BaseLoader<LoaderDomain>::loadConv2D(const Operator *op, ir::Graph &subg)
param.dilation.width_factor = options->dilation_w_factor();
param.dilation.height_factor = options->dilation_h_factor();
- loadOperationTo<ir::operation::Conv2D>(op, subg, param);
+ const auto conv = loadOperationTo<ir::operation::Conv2D>(op, subg, param);
+
+ // TFLite support old hybrid quantization (float input/output, uint8 kernel)
+ // but it interprets weight type as init8 internally
+ const auto &input_operand =
+ subg.operands().at(conv->getInputs().at(ir::operation::Conv2D::INPUT));
+ auto &weights_operand = subg.operands().at(conv->getInputs().at(ir::operation::Conv2D::KERNEL));
+ if (input_operand.typeInfo().type() == ir::DataType::FLOAT32 &&
+ ((weights_operand.typeInfo().type() == ir::DataType::QUANT_UINT8_ASYMM) ||
+ weights_operand.typeInfo().type() == ir::DataType::QUANT_INT8_ASYMM))
+ {
+ weights_operand.type(ir::DataType::QUANT_INT8_SYMM);
+ }
}
template <typename LoaderDomain>
@@ -665,7 +678,21 @@ void BaseLoader<LoaderDomain>::loadDepthwiseConv2D(const Operator *op, ir::Graph
param.dilation.width_factor = options->dilation_w_factor();
param.dilation.height_factor = options->dilation_h_factor();
- loadOperationTo<ir::operation::DepthwiseConv2D>(op, subg, param);
+ const auto dconv = loadOperationTo<ir::operation::DepthwiseConv2D>(op, subg, param);
+
+ // TFLite does not support old hybrid quantization (float input/output, uint8 kernel)
+ // for depthwise convolution.
+ // But for consistency with Conv2D and FC, we interpret weight type as init8 internally
+ const auto &input_operand =
+ subg.operands().at(dconv->getInputs().at(ir::operation::DepthwiseConv2D::INPUT));
+ auto &weights_operand =
+ subg.operands().at(dconv->getInputs().at(ir::operation::DepthwiseConv2D::KERNEL));
+ if (input_operand.typeInfo().type() == ir::DataType::FLOAT32 &&
+ ((weights_operand.typeInfo().type() == ir::DataType::QUANT_UINT8_ASYMM) ||
+ weights_operand.typeInfo().type() == ir::DataType::QUANT_INT8_ASYMM))
+ {
+ weights_operand.type(ir::DataType::QUANT_INT8_SYMM);
+ }
}
template <typename LoaderDomain>
@@ -745,6 +772,8 @@ void BaseLoader<LoaderDomain>::loadFC(const Operator *op, ir::Graph &subg)
const auto fc = loadOperationTo<ir::operation::FullyConnected>(op, subg, param);
+ // TFLite supports old hybrid quantization (float input/output, uint8 kernel)
+ // but it interprets weight type as init8 internally
const auto &input_operand =
subg.operands().at(fc->getInputs().at(ir::operation::FullyConnected::INPUT));
auto &weights_operand =
diff --git a/runtime/onert/frontend/circle_schema/include/circle_schema_generated.h b/runtime/onert/frontend/circle_schema/include/circle_schema_generated.h
index e3c92eae0..dd6f9dcd7 100644
--- a/runtime/onert/frontend/circle_schema/include/circle_schema_generated.h
+++ b/runtime/onert/frontend/circle_schema/include/circle_schema_generated.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2019-2023 Samsung Electronics Co., Ltd. All Rights Reserved
* Copyright 2018 The TensorFlow Authors. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -45,6 +45,9 @@ struct DimensionMetadataBuilder;
struct SparsityParameters;
struct SparsityParametersBuilder;
+struct VariantSubType;
+struct VariantSubTypeBuilder;
+
struct Tensor;
struct TensorBuilder;
@@ -390,6 +393,42 @@ struct AssignVariableOptionsBuilder;
struct RandomOptions;
struct RandomOptionsBuilder;
+struct BucketizeOptions;
+struct BucketizeOptionsBuilder;
+
+struct GeluOptions;
+struct GeluOptionsBuilder;
+
+struct DynamicUpdateSliceOptions;
+struct DynamicUpdateSliceOptionsBuilder;
+
+struct UnsortedSegmentProdOptions;
+struct UnsortedSegmentProdOptionsBuilder;
+
+struct UnsortedSegmentMaxOptions;
+struct UnsortedSegmentMaxOptionsBuilder;
+
+struct UnsortedSegmentSumOptions;
+struct UnsortedSegmentSumOptionsBuilder;
+
+struct ATan2Options;
+struct ATan2OptionsBuilder;
+
+struct UnsortedSegmentMinOptions;
+struct UnsortedSegmentMinOptionsBuilder;
+
+struct SignOptions;
+struct SignOptionsBuilder;
+
+struct BitcastOptions;
+struct BitcastOptionsBuilder;
+
+struct BitwiseXorOptions;
+struct BitwiseXorOptionsBuilder;
+
+struct RightShiftOptions;
+struct RightShiftOptionsBuilder;
+
struct BCQGatherOptions;
struct BCQGatherOptionsBuilder;
@@ -441,32 +480,35 @@ enum TensorType : int8_t
TensorType_RESOURCE = 13,
TensorType_VARIANT = 14,
TensorType_UINT32 = 15,
+ TensorType_UINT16 = 16,
+ TensorType_INT4 = 17,
TensorType_MIN = TensorType_FLOAT32,
- TensorType_MAX = TensorType_UINT32
+ TensorType_MAX = TensorType_INT4
};
-inline const TensorType (&EnumValuesTensorType())[16]
+inline const TensorType (&EnumValuesTensorType())[18]
{
static const TensorType values[] = {
TensorType_FLOAT32, TensorType_FLOAT16, TensorType_INT32, TensorType_UINT8,
TensorType_INT64, TensorType_STRING, TensorType_BOOL, TensorType_INT16,
TensorType_COMPLEX64, TensorType_INT8, TensorType_FLOAT64, TensorType_COMPLEX128,
- TensorType_UINT64, TensorType_RESOURCE, TensorType_VARIANT, TensorType_UINT32};
+ TensorType_UINT64, TensorType_RESOURCE, TensorType_VARIANT, TensorType_UINT32,
+ TensorType_UINT16, TensorType_INT4};
return values;
}
inline const char *const *EnumNamesTensorType()
{
- static const char *const names[17] = {"FLOAT32", "FLOAT16", "INT32", "UINT8", "INT64",
+ static const char *const names[19] = {"FLOAT32", "FLOAT16", "INT32", "UINT8", "INT64",
"STRING", "BOOL", "INT16", "COMPLEX64", "INT8",
"FLOAT64", "COMPLEX128", "UINT64", "RESOURCE", "VARIANT",
- "UINT32", nullptr};
+ "UINT32", "UINT16", "INT4", nullptr};
return names;
}
inline const char *EnumNameTensorType(TensorType e)
{
- if (flatbuffers::IsOutRange(e, TensorType_FLOAT32, TensorType_UINT32))
+ if (flatbuffers::IsOutRange(e, TensorType_FLOAT32, TensorType_INT4))
return "";
const size_t index = static_cast<size_t>(e);
return EnumNamesTensorType()[index];
@@ -756,11 +798,26 @@ enum BuiltinOperator : int32_t
BuiltinOperator_ASSIGN_VARIABLE = 144,
BuiltinOperator_BROADCAST_ARGS = 145,
BuiltinOperator_RANDOM_STANDARD_NORMAL = 146,
+ BuiltinOperator_BUCKETIZE = 147,
+ BuiltinOperator_RANDOM_UNIFORM = 148,
+ BuiltinOperator_MULTINOMIAL = 149,
+ BuiltinOperator_GELU = 150,
+ BuiltinOperator_DYNAMIC_UPDATE_SLICE = 151,
+ BuiltinOperator_RELU_0_TO_1 = 152,
+ BuiltinOperator_UNSORTED_SEGMENT_PROD = 153,
+ BuiltinOperator_UNSORTED_SEGMENT_MAX = 154,
+ BuiltinOperator_UNSORTED_SEGMENT_SUM = 155,
+ BuiltinOperator_ATAN2 = 156,
+ BuiltinOperator_UNSORTED_SEGMENT_MIN = 157,
+ BuiltinOperator_SIGN = 158,
+ BuiltinOperator_BITCAST = 159,
+ BuiltinOperator_BITWISE_XOR = 160,
+ BuiltinOperator_RIGHT_SHIFT = 161,
BuiltinOperator_MIN = BuiltinOperator_BCQ_GATHER,
- BuiltinOperator_MAX = BuiltinOperator_RANDOM_STANDARD_NORMAL
+ BuiltinOperator_MAX = BuiltinOperator_RIGHT_SHIFT
};
-inline const BuiltinOperator (&EnumValuesBuiltinOperator())[150]
+inline const BuiltinOperator (&EnumValuesBuiltinOperator())[165]
{
static const BuiltinOperator values[] = {BuiltinOperator_BCQ_GATHER,
BuiltinOperator_BCQ_FULLY_CONNECTED,
@@ -911,13 +968,28 @@ inline const BuiltinOperator (&EnumValuesBuiltinOperator())[150]
BuiltinOperator_READ_VARIABLE,
BuiltinOperator_ASSIGN_VARIABLE,
BuiltinOperator_BROADCAST_ARGS,
- BuiltinOperator_RANDOM_STANDARD_NORMAL};
+ BuiltinOperator_RANDOM_STANDARD_NORMAL,
+ BuiltinOperator_BUCKETIZE,
+ BuiltinOperator_RANDOM_UNIFORM,
+ BuiltinOperator_MULTINOMIAL,
+ BuiltinOperator_GELU,
+ BuiltinOperator_DYNAMIC_UPDATE_SLICE,
+ BuiltinOperator_RELU_0_TO_1,
+ BuiltinOperator_UNSORTED_SEGMENT_PROD,
+ BuiltinOperator_UNSORTED_SEGMENT_MAX,
+ BuiltinOperator_UNSORTED_SEGMENT_SUM,
+ BuiltinOperator_ATAN2,
+ BuiltinOperator_UNSORTED_SEGMENT_MIN,
+ BuiltinOperator_SIGN,
+ BuiltinOperator_BITCAST,
+ BuiltinOperator_BITWISE_XOR,
+ BuiltinOperator_RIGHT_SHIFT};
return values;
}
inline const char *const *EnumNamesBuiltinOperator()
{
- static const char *const names[152] = {"BCQ_GATHER",
+ static const char *const names[167] = {"BCQ_GATHER",
"BCQ_FULLY_CONNECTED",
"INSTANCE_NORM",
"",
@@ -1068,14 +1140,28 @@ inline const char *const *EnumNamesBuiltinOperator()
"ASSIGN_VARIABLE",
"BROADCAST_ARGS",
"RANDOM_STANDARD_NORMAL",
+ "BUCKETIZE",
+ "RANDOM_UNIFORM",
+ "MULTINOMIAL",
+ "GELU",
+ "DYNAMIC_UPDATE_SLICE",
+ "RELU_0_TO_1",
+ "UNSORTED_SEGMENT_PROD",
+ "UNSORTED_SEGMENT_MAX",
+ "UNSORTED_SEGMENT_SUM",
+ "ATAN2",
+ "UNSORTED_SEGMENT_MIN",
+ "SIGN",
+ "BITCAST",
+ "BITWISE_XOR",
+ "RIGHT_SHIFT",
nullptr};
return names;
}
inline const char *EnumNameBuiltinOperator(BuiltinOperator e)
{
- if (flatbuffers::IsOutRange(e, BuiltinOperator_BCQ_GATHER,
- BuiltinOperator_RANDOM_STANDARD_NORMAL))
+ if (flatbuffers::IsOutRange(e, BuiltinOperator_BCQ_GATHER, BuiltinOperator_RIGHT_SHIFT))
return "";
const size_t index = static_cast<size_t>(e) - static_cast<size_t>(BuiltinOperator_BCQ_GATHER);
return EnumNamesBuiltinOperator()[index];
@@ -1198,6 +1284,18 @@ enum BuiltinOptions : uint8_t
BuiltinOptions_ReadVariableOptions = 112,
BuiltinOptions_AssignVariableOptions = 113,
BuiltinOptions_RandomOptions = 114,
+ BuiltinOptions_BucketizeOptions = 115,
+ BuiltinOptions_GeluOptions = 116,
+ BuiltinOptions_DynamicUpdateSliceOptions = 117,
+ BuiltinOptions_UnsortedSegmentProdOptions = 118,
+ BuiltinOptions_UnsortedSegmentMaxOptions = 119,
+ BuiltinOptions_UnsortedSegmentMinOptions = 120,
+ BuiltinOptions_UnsortedSegmentSumOptions = 121,
+ BuiltinOptions_ATan2Options = 122,
+ BuiltinOptions_SignOptions = 123,
+ BuiltinOptions_BitcastOptions = 124,
+ BuiltinOptions_BitwiseXorOptions = 125,
+ BuiltinOptions_RightShiftOptions = 126,
BuiltinOptions_BCQGatherOptions = 252,
BuiltinOptions_BCQFullyConnectedOptions = 253,
BuiltinOptions_InstanceNormOptions = 254,
@@ -1205,7 +1303,7 @@ enum BuiltinOptions : uint8_t
BuiltinOptions_MAX = BuiltinOptions_InstanceNormOptions
};
-inline const BuiltinOptions (&EnumValuesBuiltinOptions())[118]
+inline const BuiltinOptions (&EnumValuesBuiltinOptions())[130]
{
static const BuiltinOptions values[] = {BuiltinOptions_NONE,
BuiltinOptions_Conv2DOptions,
@@ -1322,6 +1420,18 @@ inline const BuiltinOptions (&EnumValuesBuiltinOptions())[118]
BuiltinOptions_ReadVariableOptions,
BuiltinOptions_AssignVariableOptions,
BuiltinOptions_RandomOptions,
+ BuiltinOptions_BucketizeOptions,
+ BuiltinOptions_GeluOptions,
+ BuiltinOptions_DynamicUpdateSliceOptions,
+ BuiltinOptions_UnsortedSegmentProdOptions,
+ BuiltinOptions_UnsortedSegmentMaxOptions,
+ BuiltinOptions_UnsortedSegmentMinOptions,
+ BuiltinOptions_UnsortedSegmentSumOptions,
+ BuiltinOptions_ATan2Options,
+ BuiltinOptions_SignOptions,
+ BuiltinOptions_BitcastOptions,
+ BuiltinOptions_BitwiseXorOptions,
+ BuiltinOptions_RightShiftOptions,
BuiltinOptions_BCQGatherOptions,
BuiltinOptions_BCQFullyConnectedOptions,
BuiltinOptions_InstanceNormOptions};
@@ -1445,18 +1555,18 @@ inline const char *const *EnumNamesBuiltinOptions()
"ReadVariableOptions",
"AssignVariableOptions",
"RandomOptions",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
+ "BucketizeOptions",
+ "GeluOptions",
+ "DynamicUpdateSliceOptions",
+ "UnsortedSegmentProdOptions",
+ "UnsortedSegmentMaxOptions",
+ "UnsortedSegmentMinOptions",
+ "UnsortedSegmentSumOptions",
+ "ATan2Options",
+ "SignOptions",
+ "BitcastOptions",
+ "BitwiseXorOptions",
+ "RightShiftOptions",
"",
"",
"",
@@ -2172,6 +2282,66 @@ template <> struct BuiltinOptionsTraits<circle::RandomOptions>
static const BuiltinOptions enum_value = BuiltinOptions_RandomOptions;
};
+template <> struct BuiltinOptionsTraits<circle::BucketizeOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_BucketizeOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::GeluOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_GeluOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::DynamicUpdateSliceOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_DynamicUpdateSliceOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::UnsortedSegmentProdOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_UnsortedSegmentProdOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::UnsortedSegmentMaxOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_UnsortedSegmentMaxOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::UnsortedSegmentMinOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_UnsortedSegmentMinOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::UnsortedSegmentSumOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_UnsortedSegmentSumOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::ATan2Options>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_ATan2Options;
+};
+
+template <> struct BuiltinOptionsTraits<circle::SignOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_SignOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::BitcastOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_BitcastOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::BitwiseXorOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_BitwiseXorOptions;
+};
+
+template <> struct BuiltinOptionsTraits<circle::RightShiftOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_RightShiftOptions;
+};
+
template <> struct BuiltinOptionsTraits<circle::BCQGatherOptions>
{
static const BuiltinOptions enum_value = BuiltinOptions_BCQGatherOptions;
@@ -3103,6 +3273,81 @@ inline flatbuffers::Offset<SparsityParameters> CreateSparsityParametersDirect(
return circle::CreateSparsityParameters(_fbb, traversal_order__, block_map__, dim_metadata__);
}
+struct VariantSubType FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef VariantSubTypeBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_SHAPE = 4,
+ VT_TYPE = 6,
+ VT_HAS_RANK = 8
+ };
+ const flatbuffers::Vector<int32_t> *shape() const
+ {
+ return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_SHAPE);
+ }
+ circle::TensorType type() const
+ {
+ return static_cast<circle::TensorType>(GetField<int8_t>(VT_TYPE, 0));
+ }
+ bool has_rank() const { return GetField<uint8_t>(VT_HAS_RANK, 0) != 0; }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_SHAPE) &&
+ verifier.VerifyVector(shape()) && VerifyField<int8_t>(verifier, VT_TYPE) &&
+ VerifyField<uint8_t>(verifier, VT_HAS_RANK) && verifier.EndTable();
+ }
+};
+
+struct VariantSubTypeBuilder
+{
+ typedef VariantSubType Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_shape(flatbuffers::Offset<flatbuffers::Vector<int32_t>> shape)
+ {
+ fbb_.AddOffset(VariantSubType::VT_SHAPE, shape);
+ }
+ void add_type(circle::TensorType type)
+ {
+ fbb_.AddElement<int8_t>(VariantSubType::VT_TYPE, static_cast<int8_t>(type), 0);
+ }
+ void add_has_rank(bool has_rank)
+ {
+ fbb_.AddElement<uint8_t>(VariantSubType::VT_HAS_RANK, static_cast<uint8_t>(has_rank), 0);
+ }
+ explicit VariantSubTypeBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<VariantSubType> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<VariantSubType>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<VariantSubType>
+CreateVariantSubType(flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::Vector<int32_t>> shape = 0,
+ circle::TensorType type = circle::TensorType_FLOAT32, bool has_rank = false)
+{
+ VariantSubTypeBuilder builder_(_fbb);
+ builder_.add_shape(shape);
+ builder_.add_has_rank(has_rank);
+ builder_.add_type(type);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<VariantSubType> CreateVariantSubTypeDirect(
+ flatbuffers::FlatBufferBuilder &_fbb, const std::vector<int32_t> *shape = nullptr,
+ circle::TensorType type = circle::TensorType_FLOAT32, bool has_rank = false)
+{
+ auto shape__ = shape ? _fbb.CreateVector<int32_t>(*shape) : 0;
+ return circle::CreateVariantSubType(_fbb, shape__, type, has_rank);
+}
+
struct Tensor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
{
typedef TensorBuilder Builder;
@@ -3115,7 +3360,9 @@ struct Tensor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
VT_QUANTIZATION = 12,
VT_IS_VARIABLE = 14,
VT_SPARSITY = 16,
- VT_SHAPE_SIGNATURE = 18
+ VT_SHAPE_SIGNATURE = 18,
+ VT_HAS_RANK = 20,
+ VT_VARIANT_TENSORS = 22
};
const flatbuffers::Vector<int32_t> *shape() const
{
@@ -3143,6 +3390,12 @@ struct Tensor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
{
return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_SHAPE_SIGNATURE);
}
+ bool has_rank() const { return GetField<uint8_t>(VT_HAS_RANK, 0) != 0; }
+ const flatbuffers::Vector<flatbuffers::Offset<circle::VariantSubType>> *variant_tensors() const
+ {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<circle::VariantSubType>> *>(
+ VT_VARIANT_TENSORS);
+ }
bool Verify(flatbuffers::Verifier &verifier) const
{
return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_SHAPE) &&
@@ -3152,7 +3405,9 @@ struct Tensor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
verifier.VerifyTable(quantization()) && VerifyField<uint8_t>(verifier, VT_IS_VARIABLE) &&
VerifyOffset(verifier, VT_SPARSITY) && verifier.VerifyTable(sparsity()) &&
VerifyOffset(verifier, VT_SHAPE_SIGNATURE) && verifier.VerifyVector(shape_signature()) &&
- verifier.EndTable();
+ VerifyField<uint8_t>(verifier, VT_HAS_RANK) &&
+ VerifyOffset(verifier, VT_VARIANT_TENSORS) && verifier.VerifyVector(variant_tensors()) &&
+ verifier.VerifyVectorOfTables(variant_tensors()) && verifier.EndTable();
}
};
@@ -3190,6 +3445,16 @@ struct TensorBuilder
{
fbb_.AddOffset(Tensor::VT_SHAPE_SIGNATURE, shape_signature);
}
+ void add_has_rank(bool has_rank)
+ {
+ fbb_.AddElement<uint8_t>(Tensor::VT_HAS_RANK, static_cast<uint8_t>(has_rank), 0);
+ }
+ void add_variant_tensors(
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::VariantSubType>>>
+ variant_tensors)
+ {
+ fbb_.AddOffset(Tensor::VT_VARIANT_TENSORS, variant_tensors);
+ }
explicit TensorBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
{
start_ = fbb_.StartTable();
@@ -3202,22 +3467,25 @@ struct TensorBuilder
}
};
-inline flatbuffers::Offset<Tensor>
-CreateTensor(flatbuffers::FlatBufferBuilder &_fbb,
- flatbuffers::Offset<flatbuffers::Vector<int32_t>> shape = 0,
- circle::TensorType type = circle::TensorType_FLOAT32, uint32_t buffer = 0,
- flatbuffers::Offset<flatbuffers::String> name = 0,
- flatbuffers::Offset<circle::QuantizationParameters> quantization = 0,
- bool is_variable = false, flatbuffers::Offset<circle::SparsityParameters> sparsity = 0,
- flatbuffers::Offset<flatbuffers::Vector<int32_t>> shape_signature = 0)
+inline flatbuffers::Offset<Tensor> CreateTensor(
+ flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::Offset<flatbuffers::Vector<int32_t>> shape = 0,
+ circle::TensorType type = circle::TensorType_FLOAT32, uint32_t buffer = 0,
+ flatbuffers::Offset<flatbuffers::String> name = 0,
+ flatbuffers::Offset<circle::QuantizationParameters> quantization = 0, bool is_variable = false,
+ flatbuffers::Offset<circle::SparsityParameters> sparsity = 0,
+ flatbuffers::Offset<flatbuffers::Vector<int32_t>> shape_signature = 0, bool has_rank = false,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::VariantSubType>>>
+ variant_tensors = 0)
{
TensorBuilder builder_(_fbb);
+ builder_.add_variant_tensors(variant_tensors);
builder_.add_shape_signature(shape_signature);
builder_.add_sparsity(sparsity);
builder_.add_quantization(quantization);
builder_.add_name(name);
builder_.add_buffer(buffer);
builder_.add_shape(shape);
+ builder_.add_has_rank(has_rank);
builder_.add_is_variable(is_variable);
builder_.add_type(type);
return builder_.Finish();
@@ -3228,13 +3496,18 @@ inline flatbuffers::Offset<Tensor> CreateTensorDirect(
circle::TensorType type = circle::TensorType_FLOAT32, uint32_t buffer = 0,
const char *name = nullptr, flatbuffers::Offset<circle::QuantizationParameters> quantization = 0,
bool is_variable = false, flatbuffers::Offset<circle::SparsityParameters> sparsity = 0,
- const std::vector<int32_t> *shape_signature = nullptr)
+ const std::vector<int32_t> *shape_signature = nullptr, bool has_rank = false,
+ const std::vector<flatbuffers::Offset<circle::VariantSubType>> *variant_tensors = nullptr)
{
auto shape__ = shape ? _fbb.CreateVector<int32_t>(*shape) : 0;
auto name__ = name ? _fbb.CreateString(name) : 0;
auto shape_signature__ = shape_signature ? _fbb.CreateVector<int32_t>(*shape_signature) : 0;
+ auto variant_tensors__ =
+ variant_tensors
+ ? _fbb.CreateVector<flatbuffers::Offset<circle::VariantSubType>>(*variant_tensors)
+ : 0;
return circle::CreateTensor(_fbb, shape__, type, buffer, name__, quantization, is_variable,
- sparsity, shape_signature__);
+ sparsity, shape_signature__, has_rank, variant_tensors__);
}
struct Conv2DOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
@@ -4561,7 +4834,8 @@ struct UnidirectionalSequenceLSTMOptions FLATBUFFERS_FINAL_CLASS : private flatb
VT_CELL_CLIP = 6,
VT_PROJ_CLIP = 8,
VT_TIME_MAJOR = 10,
- VT_ASYMMETRIC_QUANTIZE_INPUTS = 12
+ VT_ASYMMETRIC_QUANTIZE_INPUTS = 12,
+ VT_DIAGONAL_RECURRENT_TENSORS = 14
};
circle::ActivationFunctionType fused_activation_function() const
{
@@ -4575,6 +4849,10 @@ struct UnidirectionalSequenceLSTMOptions FLATBUFFERS_FINAL_CLASS : private flatb
{
return GetField<uint8_t>(VT_ASYMMETRIC_QUANTIZE_INPUTS, 0) != 0;
}
+ bool diagonal_recurrent_tensors() const
+ {
+ return GetField<uint8_t>(VT_DIAGONAL_RECURRENT_TENSORS, 0) != 0;
+ }
bool Verify(flatbuffers::Verifier &verifier) const
{
return VerifyTableStart(verifier) &&
@@ -4582,7 +4860,8 @@ struct UnidirectionalSequenceLSTMOptions FLATBUFFERS_FINAL_CLASS : private flatb
VerifyField<float>(verifier, VT_CELL_CLIP) &&
VerifyField<float>(verifier, VT_PROJ_CLIP) &&
VerifyField<uint8_t>(verifier, VT_TIME_MAJOR) &&
- VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS) && verifier.EndTable();
+ VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS) &&
+ VerifyField<uint8_t>(verifier, VT_DIAGONAL_RECURRENT_TENSORS) && verifier.EndTable();
}
};
@@ -4614,6 +4893,11 @@ struct UnidirectionalSequenceLSTMOptionsBuilder
fbb_.AddElement<uint8_t>(UnidirectionalSequenceLSTMOptions::VT_ASYMMETRIC_QUANTIZE_INPUTS,
static_cast<uint8_t>(asymmetric_quantize_inputs), 0);
}
+ void add_diagonal_recurrent_tensors(bool diagonal_recurrent_tensors)
+ {
+ fbb_.AddElement<uint8_t>(UnidirectionalSequenceLSTMOptions::VT_DIAGONAL_RECURRENT_TENSORS,
+ static_cast<uint8_t>(diagonal_recurrent_tensors), 0);
+ }
explicit UnidirectionalSequenceLSTMOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb)
{
@@ -4632,11 +4916,12 @@ CreateUnidirectionalSequenceLSTMOptions(
flatbuffers::FlatBufferBuilder &_fbb,
circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE,
float cell_clip = 0.0f, float proj_clip = 0.0f, bool time_major = false,
- bool asymmetric_quantize_inputs = false)
+ bool asymmetric_quantize_inputs = false, bool diagonal_recurrent_tensors = false)
{
UnidirectionalSequenceLSTMOptionsBuilder builder_(_fbb);
builder_.add_proj_clip(proj_clip);
builder_.add_cell_clip(cell_clip);
+ builder_.add_diagonal_recurrent_tensors(diagonal_recurrent_tensors);
builder_.add_asymmetric_quantize_inputs(asymmetric_quantize_inputs);
builder_.add_time_major(time_major);
builder_.add_fused_activation_function(fused_activation_function);
@@ -6350,7 +6635,8 @@ struct TransposeConvOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
{
VT_PADDING = 4,
VT_STRIDE_W = 6,
- VT_STRIDE_H = 8
+ VT_STRIDE_H = 8,
+ VT_FUSED_ACTIVATION_FUNCTION = 10
};
circle::Padding padding() const
{
@@ -6358,11 +6644,17 @@ struct TransposeConvOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
}
int32_t stride_w() const { return GetField<int32_t>(VT_STRIDE_W, 0); }
int32_t stride_h() const { return GetField<int32_t>(VT_STRIDE_H, 0); }
+ circle::ActivationFunctionType fused_activation_function() const
+ {
+ return static_cast<circle::ActivationFunctionType>(
+ GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+ }
bool Verify(flatbuffers::Verifier &verifier) const
{
return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_PADDING) &&
VerifyField<int32_t>(verifier, VT_STRIDE_W) &&
- VerifyField<int32_t>(verifier, VT_STRIDE_H) && verifier.EndTable();
+ VerifyField<int32_t>(verifier, VT_STRIDE_H) &&
+ VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION) && verifier.EndTable();
}
};
@@ -6383,6 +6675,11 @@ struct TransposeConvOptionsBuilder
{
fbb_.AddElement<int32_t>(TransposeConvOptions::VT_STRIDE_H, stride_h, 0);
}
+ void add_fused_activation_function(circle::ActivationFunctionType fused_activation_function)
+ {
+ fbb_.AddElement<int8_t>(TransposeConvOptions::VT_FUSED_ACTIVATION_FUNCTION,
+ static_cast<int8_t>(fused_activation_function), 0);
+ }
explicit TransposeConvOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
{
start_ = fbb_.StartTable();
@@ -6395,14 +6692,15 @@ struct TransposeConvOptionsBuilder
}
};
-inline flatbuffers::Offset<TransposeConvOptions>
-CreateTransposeConvOptions(flatbuffers::FlatBufferBuilder &_fbb,
- circle::Padding padding = circle::Padding_SAME, int32_t stride_w = 0,
- int32_t stride_h = 0)
+inline flatbuffers::Offset<TransposeConvOptions> CreateTransposeConvOptions(
+ flatbuffers::FlatBufferBuilder &_fbb, circle::Padding padding = circle::Padding_SAME,
+ int32_t stride_w = 0, int32_t stride_h = 0,
+ circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE)
{
TransposeConvOptionsBuilder builder_(_fbb);
builder_.add_stride_h(stride_h);
builder_.add_stride_w(stride_w);
+ builder_.add_fused_activation_function(fused_activation_function);
builder_.add_padding(padding);
return builder_.Finish();
}
@@ -8506,12 +8804,12 @@ struct RandomOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
VT_SEED = 4,
VT_SEED2 = 6
};
- int32_t seed() const { return GetField<int32_t>(VT_SEED, 0); }
- int32_t seed2() const { return GetField<int32_t>(VT_SEED2, 0); }
+ int64_t seed() const { return GetField<int64_t>(VT_SEED, 0); }
+ int64_t seed2() const { return GetField<int64_t>(VT_SEED2, 0); }
bool Verify(flatbuffers::Verifier &verifier) const
{
- return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_SEED) &&
- VerifyField<int32_t>(verifier, VT_SEED2) && verifier.EndTable();
+ return VerifyTableStart(verifier) && VerifyField<int64_t>(verifier, VT_SEED) &&
+ VerifyField<int64_t>(verifier, VT_SEED2) && verifier.EndTable();
}
};
@@ -8520,8 +8818,8 @@ struct RandomOptionsBuilder
typedef RandomOptions Table;
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
- void add_seed(int32_t seed) { fbb_.AddElement<int32_t>(RandomOptions::VT_SEED, seed, 0); }
- void add_seed2(int32_t seed2) { fbb_.AddElement<int32_t>(RandomOptions::VT_SEED2, seed2, 0); }
+ void add_seed(int64_t seed) { fbb_.AddElement<int64_t>(RandomOptions::VT_SEED, seed, 0); }
+ void add_seed2(int64_t seed2) { fbb_.AddElement<int64_t>(RandomOptions::VT_SEED2, seed2, 0); }
explicit RandomOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
{
start_ = fbb_.StartTable();
@@ -8535,7 +8833,7 @@ struct RandomOptionsBuilder
};
inline flatbuffers::Offset<RandomOptions> CreateRandomOptions(flatbuffers::FlatBufferBuilder &_fbb,
- int32_t seed = 0, int32_t seed2 = 0)
+ int64_t seed = 0, int64_t seed2 = 0)
{
RandomOptionsBuilder builder_(_fbb);
builder_.add_seed2(seed2);
@@ -8543,6 +8841,434 @@ inline flatbuffers::Offset<RandomOptions> CreateRandomOptions(flatbuffers::FlatB
return builder_.Finish();
}
+struct BucketizeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef BucketizeOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_BOUNDARIES = 4
+ };
+ const flatbuffers::Vector<float> *boundaries() const
+ {
+ return GetPointer<const flatbuffers::Vector<float> *>(VT_BOUNDARIES);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_BOUNDARIES) &&
+ verifier.VerifyVector(boundaries()) && verifier.EndTable();
+ }
+};
+
+struct BucketizeOptionsBuilder
+{
+ typedef BucketizeOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_boundaries(flatbuffers::Offset<flatbuffers::Vector<float>> boundaries)
+ {
+ fbb_.AddOffset(BucketizeOptions::VT_BOUNDARIES, boundaries);
+ }
+ explicit BucketizeOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<BucketizeOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<BucketizeOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<BucketizeOptions>
+CreateBucketizeOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::Vector<float>> boundaries = 0)
+{
+ BucketizeOptionsBuilder builder_(_fbb);
+ builder_.add_boundaries(boundaries);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<BucketizeOptions>
+CreateBucketizeOptionsDirect(flatbuffers::FlatBufferBuilder &_fbb,
+ const std::vector<float> *boundaries = nullptr)
+{
+ auto boundaries__ = boundaries ? _fbb.CreateVector<float>(*boundaries) : 0;
+ return circle::CreateBucketizeOptions(_fbb, boundaries__);
+}
+
+struct GeluOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef GeluOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_APPROXIMATE = 4
+ };
+ bool approximate() const { return GetField<uint8_t>(VT_APPROXIMATE, 0) != 0; }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<uint8_t>(verifier, VT_APPROXIMATE) &&
+ verifier.EndTable();
+ }
+};
+
+struct GeluOptionsBuilder
+{
+ typedef GeluOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_approximate(bool approximate)
+ {
+ fbb_.AddElement<uint8_t>(GeluOptions::VT_APPROXIMATE, static_cast<uint8_t>(approximate), 0);
+ }
+ explicit GeluOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<GeluOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<GeluOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<GeluOptions> CreateGeluOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ bool approximate = false)
+{
+ GeluOptionsBuilder builder_(_fbb);
+ builder_.add_approximate(approximate);
+ return builder_.Finish();
+}
+
+struct DynamicUpdateSliceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef DynamicUpdateSliceOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+};
+
+struct DynamicUpdateSliceOptionsBuilder
+{
+ typedef DynamicUpdateSliceOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit DynamicUpdateSliceOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<DynamicUpdateSliceOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<DynamicUpdateSliceOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<DynamicUpdateSliceOptions>
+CreateDynamicUpdateSliceOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ DynamicUpdateSliceOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+struct UnsortedSegmentProdOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef UnsortedSegmentProdOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+};
+
+struct UnsortedSegmentProdOptionsBuilder
+{
+ typedef UnsortedSegmentProdOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit UnsortedSegmentProdOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<UnsortedSegmentProdOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<UnsortedSegmentProdOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<UnsortedSegmentProdOptions>
+CreateUnsortedSegmentProdOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ UnsortedSegmentProdOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+struct UnsortedSegmentMaxOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef UnsortedSegmentMaxOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+};
+
+struct UnsortedSegmentMaxOptionsBuilder
+{
+ typedef UnsortedSegmentMaxOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit UnsortedSegmentMaxOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<UnsortedSegmentMaxOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<UnsortedSegmentMaxOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<UnsortedSegmentMaxOptions>
+CreateUnsortedSegmentMaxOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ UnsortedSegmentMaxOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+struct UnsortedSegmentSumOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef UnsortedSegmentSumOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+};
+
+struct UnsortedSegmentSumOptionsBuilder
+{
+ typedef UnsortedSegmentSumOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit UnsortedSegmentSumOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<UnsortedSegmentSumOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<UnsortedSegmentSumOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<UnsortedSegmentSumOptions>
+CreateUnsortedSegmentSumOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ UnsortedSegmentSumOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+struct ATan2Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef ATan2OptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+};
+
+struct ATan2OptionsBuilder
+{
+ typedef ATan2Options Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit ATan2OptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<ATan2Options> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<ATan2Options>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<ATan2Options> CreateATan2Options(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ ATan2OptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+struct UnsortedSegmentMinOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef UnsortedSegmentMinOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+};
+
+struct UnsortedSegmentMinOptionsBuilder
+{
+ typedef UnsortedSegmentMinOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit UnsortedSegmentMinOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<UnsortedSegmentMinOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<UnsortedSegmentMinOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<UnsortedSegmentMinOptions>
+CreateUnsortedSegmentMinOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ UnsortedSegmentMinOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+struct SignOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef SignOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+};
+
+struct SignOptionsBuilder
+{
+ typedef SignOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit SignOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<SignOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<SignOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<SignOptions> CreateSignOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ SignOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+struct BitcastOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef BitcastOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+};
+
+struct BitcastOptionsBuilder
+{
+ typedef BitcastOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit BitcastOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<BitcastOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<BitcastOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<BitcastOptions>
+CreateBitcastOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ BitcastOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+struct BitwiseXorOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef BitwiseXorOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+};
+
+struct BitwiseXorOptionsBuilder
+{
+ typedef BitwiseXorOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit BitwiseXorOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<BitwiseXorOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<BitwiseXorOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<BitwiseXorOptions>
+CreateBitwiseXorOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ BitwiseXorOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+struct RightShiftOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef RightShiftOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+};
+
+struct RightShiftOptionsBuilder
+{
+ typedef RightShiftOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit RightShiftOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<RightShiftOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<RightShiftOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<RightShiftOptions>
+CreateRightShiftOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ RightShiftOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
struct BCQGatherOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
{
typedef BCQGatherOptionsBuilder Builder;
@@ -9513,6 +10239,78 @@ struct Operator FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
? static_cast<const circle::RandomOptions *>(builtin_options())
: nullptr;
}
+ const circle::BucketizeOptions *builtin_options_as_BucketizeOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_BucketizeOptions
+ ? static_cast<const circle::BucketizeOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::GeluOptions *builtin_options_as_GeluOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_GeluOptions
+ ? static_cast<const circle::GeluOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::DynamicUpdateSliceOptions *builtin_options_as_DynamicUpdateSliceOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_DynamicUpdateSliceOptions
+ ? static_cast<const circle::DynamicUpdateSliceOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::UnsortedSegmentProdOptions *builtin_options_as_UnsortedSegmentProdOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_UnsortedSegmentProdOptions
+ ? static_cast<const circle::UnsortedSegmentProdOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::UnsortedSegmentMaxOptions *builtin_options_as_UnsortedSegmentMaxOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_UnsortedSegmentMaxOptions
+ ? static_cast<const circle::UnsortedSegmentMaxOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::UnsortedSegmentMinOptions *builtin_options_as_UnsortedSegmentMinOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_UnsortedSegmentMinOptions
+ ? static_cast<const circle::UnsortedSegmentMinOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::UnsortedSegmentSumOptions *builtin_options_as_UnsortedSegmentSumOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_UnsortedSegmentSumOptions
+ ? static_cast<const circle::UnsortedSegmentSumOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::ATan2Options *builtin_options_as_ATan2Options() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_ATan2Options
+ ? static_cast<const circle::ATan2Options *>(builtin_options())
+ : nullptr;
+ }
+ const circle::SignOptions *builtin_options_as_SignOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_SignOptions
+ ? static_cast<const circle::SignOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::BitcastOptions *builtin_options_as_BitcastOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_BitcastOptions
+ ? static_cast<const circle::BitcastOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::BitwiseXorOptions *builtin_options_as_BitwiseXorOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_BitwiseXorOptions
+ ? static_cast<const circle::BitwiseXorOptions *>(builtin_options())
+ : nullptr;
+ }
+ const circle::RightShiftOptions *builtin_options_as_RightShiftOptions() const
+ {
+ return builtin_options_type() == circle::BuiltinOptions_RightShiftOptions
+ ? static_cast<const circle::RightShiftOptions *>(builtin_options())
+ : nullptr;
+ }
const circle::BCQGatherOptions *builtin_options_as_BCQGatherOptions() const
{
return builtin_options_type() == circle::BuiltinOptions_BCQGatherOptions
@@ -10301,6 +11099,86 @@ inline const circle::RandomOptions *Operator::builtin_options_as<circle::RandomO
}
template <>
+inline const circle::BucketizeOptions *
+Operator::builtin_options_as<circle::BucketizeOptions>() const
+{
+ return builtin_options_as_BucketizeOptions();
+}
+
+template <>
+inline const circle::GeluOptions *Operator::builtin_options_as<circle::GeluOptions>() const
+{
+ return builtin_options_as_GeluOptions();
+}
+
+template <>
+inline const circle::DynamicUpdateSliceOptions *
+Operator::builtin_options_as<circle::DynamicUpdateSliceOptions>() const
+{
+ return builtin_options_as_DynamicUpdateSliceOptions();
+}
+
+template <>
+inline const circle::UnsortedSegmentProdOptions *
+Operator::builtin_options_as<circle::UnsortedSegmentProdOptions>() const
+{
+ return builtin_options_as_UnsortedSegmentProdOptions();
+}
+
+template <>
+inline const circle::UnsortedSegmentMaxOptions *
+Operator::builtin_options_as<circle::UnsortedSegmentMaxOptions>() const
+{
+ return builtin_options_as_UnsortedSegmentMaxOptions();
+}
+
+template <>
+inline const circle::UnsortedSegmentMinOptions *
+Operator::builtin_options_as<circle::UnsortedSegmentMinOptions>() const
+{
+ return builtin_options_as_UnsortedSegmentMinOptions();
+}
+
+template <>
+inline const circle::UnsortedSegmentSumOptions *
+Operator::builtin_options_as<circle::UnsortedSegmentSumOptions>() const
+{
+ return builtin_options_as_UnsortedSegmentSumOptions();
+}
+
+template <>
+inline const circle::ATan2Options *Operator::builtin_options_as<circle::ATan2Options>() const
+{
+ return builtin_options_as_ATan2Options();
+}
+
+template <>
+inline const circle::SignOptions *Operator::builtin_options_as<circle::SignOptions>() const
+{
+ return builtin_options_as_SignOptions();
+}
+
+template <>
+inline const circle::BitcastOptions *Operator::builtin_options_as<circle::BitcastOptions>() const
+{
+ return builtin_options_as_BitcastOptions();
+}
+
+template <>
+inline const circle::BitwiseXorOptions *
+Operator::builtin_options_as<circle::BitwiseXorOptions>() const
+{
+ return builtin_options_as_BitwiseXorOptions();
+}
+
+template <>
+inline const circle::RightShiftOptions *
+Operator::builtin_options_as<circle::RightShiftOptions>() const
+{
+ return builtin_options_as_RightShiftOptions();
+}
+
+template <>
inline const circle::BCQGatherOptions *
Operator::builtin_options_as<circle::BCQGatherOptions>() const
{
@@ -11667,6 +12545,66 @@ inline bool VerifyBuiltinOptions(flatbuffers::Verifier &verifier, const void *ob
auto ptr = reinterpret_cast<const circle::RandomOptions *>(obj);
return verifier.VerifyTable(ptr);
}
+ case BuiltinOptions_BucketizeOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::BucketizeOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_GeluOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::GeluOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_DynamicUpdateSliceOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::DynamicUpdateSliceOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_UnsortedSegmentProdOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::UnsortedSegmentProdOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_UnsortedSegmentMaxOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::UnsortedSegmentMaxOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_UnsortedSegmentMinOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::UnsortedSegmentMinOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_UnsortedSegmentSumOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::UnsortedSegmentSumOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_ATan2Options:
+ {
+ auto ptr = reinterpret_cast<const circle::ATan2Options *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_SignOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::SignOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_BitcastOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::BitcastOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_BitwiseXorOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::BitwiseXorOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_RightShiftOptions:
+ {
+ auto ptr = reinterpret_cast<const circle::RightShiftOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
case BuiltinOptions_BCQGatherOptions:
{
auto ptr = reinterpret_cast<const circle::BCQGatherOptions *>(obj);
diff --git a/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksModel.cc b/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksModel.cc
index a641368ec..837dac954 100644
--- a/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksModel.cc
+++ b/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksModel.cc
@@ -261,8 +261,8 @@ void ANeuralNetworksModel::setOptionalOperand(const onert::ir::OperandIndex idx)
void ANeuralNetworksModel::fillOptionalOperand(void)
{
- _graph->operations().iterate([&](const onert::ir::OperationIndex &, onert::ir::Operation &node) {
- for (auto input : node.getInputs())
+ _graph->operations().iterate([&](const onert::ir::OperationIndex &, onert::ir::IOperation &node) {
+ for (auto &&input : node.getInputs())
{
// TODO fill default value for optional operands
if (_optional_operands.find(input) != _optional_operands.end())
diff --git a/runtime/onert/frontend/tflite/src/tflite_schema_generated.h b/runtime/onert/frontend/tflite/src/tflite_schema_generated.h
index cec5bce74..7ad3c75bd 100644
--- a/runtime/onert/frontend/tflite/src/tflite_schema_generated.h
+++ b/runtime/onert/frontend/tflite/src/tflite_schema_generated.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2019-2023 Samsung Electronics Co., Ltd. All Rights Reserved
* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
// automatically generated by the FlatBuffers compiler, do not modify
#ifndef FLATBUFFERS_GENERATED_TFLITESCHEMA_ONERT_TFLITE_H_
@@ -391,6 +390,27 @@ struct AssignVariableOptionsBuilder;
struct RandomOptions;
struct RandomOptionsBuilder;
+struct BucketizeOptions;
+struct BucketizeOptionsBuilder;
+
+struct GeluOptions;
+struct GeluOptionsBuilder;
+
+struct DynamicUpdateSliceOptions;
+struct DynamicUpdateSliceOptionsBuilder;
+
+struct UnsortedSegmentProdOptions;
+struct UnsortedSegmentProdOptionsBuilder;
+
+struct UnsortedSegmentMaxOptions;
+struct UnsortedSegmentMaxOptionsBuilder;
+
+struct UnsortedSegmentSumOptions;
+struct UnsortedSegmentSumOptionsBuilder;
+
+struct ATan2Options;
+struct ATan2OptionsBuilder;
+
struct OperatorCode;
struct OperatorCodeBuilder;
@@ -433,32 +453,34 @@ enum TensorType : int8_t
TensorType_RESOURCE = 13,
TensorType_VARIANT = 14,
TensorType_UINT32 = 15,
+ TensorType_UINT16 = 16,
TensorType_MIN = TensorType_FLOAT32,
- TensorType_MAX = TensorType_UINT32
+ TensorType_MAX = TensorType_UINT16
};
-inline const TensorType (&EnumValuesTensorType())[16]
+inline const TensorType (&EnumValuesTensorType())[17]
{
static const TensorType values[] = {
TensorType_FLOAT32, TensorType_FLOAT16, TensorType_INT32, TensorType_UINT8,
TensorType_INT64, TensorType_STRING, TensorType_BOOL, TensorType_INT16,
TensorType_COMPLEX64, TensorType_INT8, TensorType_FLOAT64, TensorType_COMPLEX128,
- TensorType_UINT64, TensorType_RESOURCE, TensorType_VARIANT, TensorType_UINT32};
+ TensorType_UINT64, TensorType_RESOURCE, TensorType_VARIANT, TensorType_UINT32,
+ TensorType_UINT16};
return values;
}
inline const char *const *EnumNamesTensorType()
{
- static const char *const names[17] = {"FLOAT32", "FLOAT16", "INT32", "UINT8", "INT64",
+ static const char *const names[18] = {"FLOAT32", "FLOAT16", "INT32", "UINT8", "INT64",
"STRING", "BOOL", "INT16", "COMPLEX64", "INT8",
"FLOAT64", "COMPLEX128", "UINT64", "RESOURCE", "VARIANT",
- "UINT32", nullptr};
+ "UINT32", "UINT16", nullptr};
return names;
}
inline const char *EnumNameTensorType(TensorType e)
{
- if (flatbuffers::IsOutRange(e, TensorType_FLOAT32, TensorType_UINT32))
+ if (flatbuffers::IsOutRange(e, TensorType_FLOAT32, TensorType_UINT16))
return "";
const size_t index = static_cast<size_t>(e);
return EnumNamesTensorType()[index];
@@ -745,11 +767,21 @@ enum BuiltinOperator : int32_t
BuiltinOperator_ASSIGN_VARIABLE = 144,
BuiltinOperator_BROADCAST_ARGS = 145,
BuiltinOperator_RANDOM_STANDARD_NORMAL = 146,
+ BuiltinOperator_BUCKETIZE = 147,
+ BuiltinOperator_RANDOM_UNIFORM = 148,
+ BuiltinOperator_MULTINOMIAL = 149,
+ BuiltinOperator_GELU = 150,
+ BuiltinOperator_DYNAMIC_UPDATE_SLICE = 151,
+ BuiltinOperator_RELU_0_TO_1 = 152,
+ BuiltinOperator_UNSORTED_SEGMENT_PROD = 153,
+ BuiltinOperator_UNSORTED_SEGMENT_MAX = 154,
+ BuiltinOperator_UNSORTED_SEGMENT_SUM = 155,
+ BuiltinOperator_ATAN2 = 156,
BuiltinOperator_MIN = BuiltinOperator_ADD,
- BuiltinOperator_MAX = BuiltinOperator_RANDOM_STANDARD_NORMAL
+ BuiltinOperator_MAX = BuiltinOperator_ATAN2
};
-inline const BuiltinOperator (&EnumValuesBuiltinOperator())[147]
+inline const BuiltinOperator (&EnumValuesBuiltinOperator())[157]
{
static const BuiltinOperator values[] = {BuiltinOperator_ADD,
BuiltinOperator_AVERAGE_POOL_2D,
@@ -897,13 +929,23 @@ inline const BuiltinOperator (&EnumValuesBuiltinOperator())[147]
BuiltinOperator_READ_VARIABLE,
BuiltinOperator_ASSIGN_VARIABLE,
BuiltinOperator_BROADCAST_ARGS,
- BuiltinOperator_RANDOM_STANDARD_NORMAL};
+ BuiltinOperator_RANDOM_STANDARD_NORMAL,
+ BuiltinOperator_BUCKETIZE,
+ BuiltinOperator_RANDOM_UNIFORM,
+ BuiltinOperator_MULTINOMIAL,
+ BuiltinOperator_GELU,
+ BuiltinOperator_DYNAMIC_UPDATE_SLICE,
+ BuiltinOperator_RELU_0_TO_1,
+ BuiltinOperator_UNSORTED_SEGMENT_PROD,
+ BuiltinOperator_UNSORTED_SEGMENT_MAX,
+ BuiltinOperator_UNSORTED_SEGMENT_SUM,
+ BuiltinOperator_ATAN2};
return values;
}
inline const char *const *EnumNamesBuiltinOperator()
{
- static const char *const names[148] = {"ADD",
+ static const char *const names[158] = {"ADD",
"AVERAGE_POOL_2D",
"CONCATENATION",
"CONV_2D",
@@ -1050,13 +1092,23 @@ inline const char *const *EnumNamesBuiltinOperator()
"ASSIGN_VARIABLE",
"BROADCAST_ARGS",
"RANDOM_STANDARD_NORMAL",
+ "BUCKETIZE",
+ "RANDOM_UNIFORM",
+ "MULTINOMIAL",
+ "GELU",
+ "DYNAMIC_UPDATE_SLICE",
+ "RELU_0_TO_1",
+ "UNSORTED_SEGMENT_PROD",
+ "UNSORTED_SEGMENT_MAX",
+ "UNSORTED_SEGMENT_SUM",
+ "ATAN2",
nullptr};
return names;
}
inline const char *EnumNameBuiltinOperator(BuiltinOperator e)
{
- if (flatbuffers::IsOutRange(e, BuiltinOperator_ADD, BuiltinOperator_RANDOM_STANDARD_NORMAL))
+ if (flatbuffers::IsOutRange(e, BuiltinOperator_ADD, BuiltinOperator_ATAN2))
return "";
const size_t index = static_cast<size_t>(e);
return EnumNamesBuiltinOperator()[index];
@@ -1179,11 +1231,18 @@ enum BuiltinOptions : uint8_t
BuiltinOptions_ReadVariableOptions = 112,
BuiltinOptions_AssignVariableOptions = 113,
BuiltinOptions_RandomOptions = 114,
+ BuiltinOptions_BucketizeOptions = 115,
+ BuiltinOptions_GeluOptions = 116,
+ BuiltinOptions_DynamicUpdateSliceOptions = 117,
+ BuiltinOptions_UnsortedSegmentProdOptions = 118,
+ BuiltinOptions_UnsortedSegmentMaxOptions = 119,
+ BuiltinOptions_UnsortedSegmentSumOptions = 120,
+ BuiltinOptions_ATan2Options = 121,
BuiltinOptions_MIN = BuiltinOptions_NONE,
- BuiltinOptions_MAX = BuiltinOptions_RandomOptions
+ BuiltinOptions_MAX = BuiltinOptions_ATan2Options
};
-inline const BuiltinOptions (&EnumValuesBuiltinOptions())[115]
+inline const BuiltinOptions (&EnumValuesBuiltinOptions())[122]
{
static const BuiltinOptions values[] = {BuiltinOptions_NONE,
BuiltinOptions_Conv2DOptions,
@@ -1299,13 +1358,20 @@ inline const BuiltinOptions (&EnumValuesBuiltinOptions())[115]
BuiltinOptions_VarHandleOptions,
BuiltinOptions_ReadVariableOptions,
BuiltinOptions_AssignVariableOptions,
- BuiltinOptions_RandomOptions};
+ BuiltinOptions_RandomOptions,
+ BuiltinOptions_BucketizeOptions,
+ BuiltinOptions_GeluOptions,
+ BuiltinOptions_DynamicUpdateSliceOptions,
+ BuiltinOptions_UnsortedSegmentProdOptions,
+ BuiltinOptions_UnsortedSegmentMaxOptions,
+ BuiltinOptions_UnsortedSegmentSumOptions,
+ BuiltinOptions_ATan2Options};
return values;
}
inline const char *const *EnumNamesBuiltinOptions()
{
- static const char *const names[116] = {"NONE",
+ static const char *const names[123] = {"NONE",
"Conv2DOptions",
"DepthwiseConv2DOptions",
"ConcatEmbeddingsOptions",
@@ -1420,13 +1486,20 @@ inline const char *const *EnumNamesBuiltinOptions()
"ReadVariableOptions",
"AssignVariableOptions",
"RandomOptions",
+ "BucketizeOptions",
+ "GeluOptions",
+ "DynamicUpdateSliceOptions",
+ "UnsortedSegmentProdOptions",
+ "UnsortedSegmentMaxOptions",
+ "UnsortedSegmentSumOptions",
+ "ATan2Options",
nullptr};
return names;
}
inline const char *EnumNameBuiltinOptions(BuiltinOptions e)
{
- if (flatbuffers::IsOutRange(e, BuiltinOptions_NONE, BuiltinOptions_RandomOptions))
+ if (flatbuffers::IsOutRange(e, BuiltinOptions_NONE, BuiltinOptions_ATan2Options))
return "";
const size_t index = static_cast<size_t>(e);
return EnumNamesBuiltinOptions()[index];
@@ -2007,6 +2080,41 @@ template <> struct BuiltinOptionsTraits<onert_tflite::RandomOptions>
static const BuiltinOptions enum_value = BuiltinOptions_RandomOptions;
};
+template <> struct BuiltinOptionsTraits<onert_tflite::BucketizeOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_BucketizeOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::GeluOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_GeluOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::DynamicUpdateSliceOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_DynamicUpdateSliceOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::UnsortedSegmentProdOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_UnsortedSegmentProdOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::UnsortedSegmentMaxOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_UnsortedSegmentMaxOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::UnsortedSegmentSumOptions>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_UnsortedSegmentSumOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::ATan2Options>
+{
+ static const BuiltinOptions enum_value = BuiltinOptions_ATan2Options;
+};
+
bool VerifyBuiltinOptions(flatbuffers::Verifier &verifier, const void *obj, BuiltinOptions type);
bool VerifyBuiltinOptionsVector(flatbuffers::Verifier &verifier,
const flatbuffers::Vector<flatbuffers::Offset<void>> *values,
@@ -2917,7 +3025,8 @@ struct Tensor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
VT_QUANTIZATION = 12,
VT_IS_VARIABLE = 14,
VT_SPARSITY = 16,
- VT_SHAPE_SIGNATURE = 18
+ VT_SHAPE_SIGNATURE = 18,
+ VT_HAS_RANK = 20
};
const flatbuffers::Vector<int32_t> *shape() const
{
@@ -2945,6 +3054,7 @@ struct Tensor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
{
return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_SHAPE_SIGNATURE);
}
+ bool has_rank() const { return GetField<uint8_t>(VT_HAS_RANK, 0) != 0; }
bool Verify(flatbuffers::Verifier &verifier) const
{
return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_SHAPE) &&
@@ -2954,7 +3064,7 @@ struct Tensor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
verifier.VerifyTable(quantization()) && VerifyField<uint8_t>(verifier, VT_IS_VARIABLE) &&
VerifyOffset(verifier, VT_SPARSITY) && verifier.VerifyTable(sparsity()) &&
VerifyOffset(verifier, VT_SHAPE_SIGNATURE) && verifier.VerifyVector(shape_signature()) &&
- verifier.EndTable();
+ VerifyField<uint8_t>(verifier, VT_HAS_RANK) && verifier.EndTable();
}
};
@@ -2992,6 +3102,10 @@ struct TensorBuilder
{
fbb_.AddOffset(Tensor::VT_SHAPE_SIGNATURE, shape_signature);
}
+ void add_has_rank(bool has_rank)
+ {
+ fbb_.AddElement<uint8_t>(Tensor::VT_HAS_RANK, static_cast<uint8_t>(has_rank), 0);
+ }
explicit TensorBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
{
start_ = fbb_.StartTable();
@@ -3010,7 +3124,7 @@ inline flatbuffers::Offset<Tensor> CreateTensor(
flatbuffers::Offset<flatbuffers::String> name = 0,
flatbuffers::Offset<onert_tflite::QuantizationParameters> quantization = 0,
bool is_variable = false, flatbuffers::Offset<onert_tflite::SparsityParameters> sparsity = 0,
- flatbuffers::Offset<flatbuffers::Vector<int32_t>> shape_signature = 0)
+ flatbuffers::Offset<flatbuffers::Vector<int32_t>> shape_signature = 0, bool has_rank = false)
{
TensorBuilder builder_(_fbb);
builder_.add_shape_signature(shape_signature);
@@ -3019,6 +3133,7 @@ inline flatbuffers::Offset<Tensor> CreateTensor(
builder_.add_name(name);
builder_.add_buffer(buffer);
builder_.add_shape(shape);
+ builder_.add_has_rank(has_rank);
builder_.add_is_variable(is_variable);
builder_.add_type(type);
return builder_.Finish();
@@ -3030,13 +3145,13 @@ inline flatbuffers::Offset<Tensor> CreateTensorDirect(
const char *name = nullptr,
flatbuffers::Offset<onert_tflite::QuantizationParameters> quantization = 0,
bool is_variable = false, flatbuffers::Offset<onert_tflite::SparsityParameters> sparsity = 0,
- const std::vector<int32_t> *shape_signature = nullptr)
+ const std::vector<int32_t> *shape_signature = nullptr, bool has_rank = false)
{
auto shape__ = shape ? _fbb.CreateVector<int32_t>(*shape) : 0;
auto name__ = name ? _fbb.CreateString(name) : 0;
auto shape_signature__ = shape_signature ? _fbb.CreateVector<int32_t>(*shape_signature) : 0;
return onert_tflite::CreateTensor(_fbb, shape__, type, buffer, name__, quantization, is_variable,
- sparsity, shape_signature__);
+ sparsity, shape_signature__, has_rank);
}
struct Conv2DOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
@@ -8325,12 +8440,12 @@ struct RandomOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
VT_SEED = 4,
VT_SEED2 = 6
};
- int32_t seed() const { return GetField<int32_t>(VT_SEED, 0); }
- int32_t seed2() const { return GetField<int32_t>(VT_SEED2, 0); }
+ int64_t seed() const { return GetField<int64_t>(VT_SEED, 0); }
+ int64_t seed2() const { return GetField<int64_t>(VT_SEED2, 0); }
bool Verify(flatbuffers::Verifier &verifier) const
{
- return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_SEED) &&
- VerifyField<int32_t>(verifier, VT_SEED2) && verifier.EndTable();
+ return VerifyTableStart(verifier) && VerifyField<int64_t>(verifier, VT_SEED) &&
+ VerifyField<int64_t>(verifier, VT_SEED2) && verifier.EndTable();
}
};
@@ -8339,8 +8454,8 @@ struct RandomOptionsBuilder
typedef RandomOptions Table;
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
- void add_seed(int32_t seed) { fbb_.AddElement<int32_t>(RandomOptions::VT_SEED, seed, 0); }
- void add_seed2(int32_t seed2) { fbb_.AddElement<int32_t>(RandomOptions::VT_SEED2, seed2, 0); }
+ void add_seed(int64_t seed) { fbb_.AddElement<int64_t>(RandomOptions::VT_SEED, seed, 0); }
+ void add_seed2(int64_t seed2) { fbb_.AddElement<int64_t>(RandomOptions::VT_SEED2, seed2, 0); }
explicit RandomOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
{
start_ = fbb_.StartTable();
@@ -8354,7 +8469,7 @@ struct RandomOptionsBuilder
};
inline flatbuffers::Offset<RandomOptions> CreateRandomOptions(flatbuffers::FlatBufferBuilder &_fbb,
- int32_t seed = 0, int32_t seed2 = 0)
+ int64_t seed = 0, int64_t seed2 = 0)
{
RandomOptionsBuilder builder_(_fbb);
builder_.add_seed2(seed2);
@@ -8362,6 +8477,270 @@ inline flatbuffers::Offset<RandomOptions> CreateRandomOptions(flatbuffers::FlatB
return builder_.Finish();
}
+struct BucketizeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef BucketizeOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_BOUNDARIES = 4
+ };
+ const flatbuffers::Vector<float> *boundaries() const
+ {
+ return GetPointer<const flatbuffers::Vector<float> *>(VT_BOUNDARIES);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_BOUNDARIES) &&
+ verifier.VerifyVector(boundaries()) && verifier.EndTable();
+ }
+};
+
+struct BucketizeOptionsBuilder
+{
+ typedef BucketizeOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_boundaries(flatbuffers::Offset<flatbuffers::Vector<float>> boundaries)
+ {
+ fbb_.AddOffset(BucketizeOptions::VT_BOUNDARIES, boundaries);
+ }
+ explicit BucketizeOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<BucketizeOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<BucketizeOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<BucketizeOptions>
+CreateBucketizeOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::Vector<float>> boundaries = 0)
+{
+ BucketizeOptionsBuilder builder_(_fbb);
+ builder_.add_boundaries(boundaries);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<BucketizeOptions>
+CreateBucketizeOptionsDirect(flatbuffers::FlatBufferBuilder &_fbb,
+ const std::vector<float> *boundaries = nullptr)
+{
+ auto boundaries__ = boundaries ? _fbb.CreateVector<float>(*boundaries) : 0;
+ return onert_tflite::CreateBucketizeOptions(_fbb, boundaries__);
+}
+
+struct GeluOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef GeluOptionsBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+ {
+ VT_APPROXIMATE = 4
+ };
+ bool approximate() const { return GetField<uint8_t>(VT_APPROXIMATE, 0) != 0; }
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && VerifyField<uint8_t>(verifier, VT_APPROXIMATE) &&
+ verifier.EndTable();
+ }
+};
+
+struct GeluOptionsBuilder
+{
+ typedef GeluOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_approximate(bool approximate)
+ {
+ fbb_.AddElement<uint8_t>(GeluOptions::VT_APPROXIMATE, static_cast<uint8_t>(approximate), 0);
+ }
+ explicit GeluOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<GeluOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<GeluOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<GeluOptions> CreateGeluOptions(flatbuffers::FlatBufferBuilder &_fbb,
+ bool approximate = false)
+{
+ GeluOptionsBuilder builder_(_fbb);
+ builder_.add_approximate(approximate);
+ return builder_.Finish();
+}
+
+struct DynamicUpdateSliceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef DynamicUpdateSliceOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+};
+
+struct DynamicUpdateSliceOptionsBuilder
+{
+ typedef DynamicUpdateSliceOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit DynamicUpdateSliceOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<DynamicUpdateSliceOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<DynamicUpdateSliceOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<DynamicUpdateSliceOptions>
+CreateDynamicUpdateSliceOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ DynamicUpdateSliceOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+struct UnsortedSegmentProdOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef UnsortedSegmentProdOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+};
+
+struct UnsortedSegmentProdOptionsBuilder
+{
+ typedef UnsortedSegmentProdOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit UnsortedSegmentProdOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<UnsortedSegmentProdOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<UnsortedSegmentProdOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<UnsortedSegmentProdOptions>
+CreateUnsortedSegmentProdOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ UnsortedSegmentProdOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+struct UnsortedSegmentMaxOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef UnsortedSegmentMaxOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+};
+
+struct UnsortedSegmentMaxOptionsBuilder
+{
+ typedef UnsortedSegmentMaxOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit UnsortedSegmentMaxOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<UnsortedSegmentMaxOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<UnsortedSegmentMaxOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<UnsortedSegmentMaxOptions>
+CreateUnsortedSegmentMaxOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ UnsortedSegmentMaxOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+struct UnsortedSegmentSumOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef UnsortedSegmentSumOptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+};
+
+struct UnsortedSegmentSumOptionsBuilder
+{
+ typedef UnsortedSegmentSumOptions Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit UnsortedSegmentSumOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<UnsortedSegmentSumOptions> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<UnsortedSegmentSumOptions>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<UnsortedSegmentSumOptions>
+CreateUnsortedSegmentSumOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ UnsortedSegmentSumOptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
+struct ATan2Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+ typedef ATan2OptionsBuilder Builder;
+ bool Verify(flatbuffers::Verifier &verifier) const
+ {
+ return VerifyTableStart(verifier) && verifier.EndTable();
+ }
+};
+
+struct ATan2OptionsBuilder
+{
+ typedef ATan2Options Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ explicit ATan2OptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+ {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<ATan2Options> Finish()
+ {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<ATan2Options>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<ATan2Options> CreateATan2Options(flatbuffers::FlatBufferBuilder &_fbb)
+{
+ ATan2OptionsBuilder builder_(_fbb);
+ return builder_.Finish();
+}
+
struct OperatorCode FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
{
typedef OperatorCodeBuilder Builder;
@@ -9173,6 +9552,52 @@ struct Operator FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
? static_cast<const onert_tflite::RandomOptions *>(builtin_options())
: nullptr;
}
+ const onert_tflite::BucketizeOptions *builtin_options_as_BucketizeOptions() const
+ {
+ return builtin_options_type() == onert_tflite::BuiltinOptions_BucketizeOptions
+ ? static_cast<const onert_tflite::BucketizeOptions *>(builtin_options())
+ : nullptr;
+ }
+ const onert_tflite::GeluOptions *builtin_options_as_GeluOptions() const
+ {
+ return builtin_options_type() == onert_tflite::BuiltinOptions_GeluOptions
+ ? static_cast<const onert_tflite::GeluOptions *>(builtin_options())
+ : nullptr;
+ }
+ const onert_tflite::DynamicUpdateSliceOptions *
+ builtin_options_as_DynamicUpdateSliceOptions() const
+ {
+ return builtin_options_type() == onert_tflite::BuiltinOptions_DynamicUpdateSliceOptions
+ ? static_cast<const onert_tflite::DynamicUpdateSliceOptions *>(builtin_options())
+ : nullptr;
+ }
+ const onert_tflite::UnsortedSegmentProdOptions *
+ builtin_options_as_UnsortedSegmentProdOptions() const
+ {
+ return builtin_options_type() == onert_tflite::BuiltinOptions_UnsortedSegmentProdOptions
+ ? static_cast<const onert_tflite::UnsortedSegmentProdOptions *>(builtin_options())
+ : nullptr;
+ }
+ const onert_tflite::UnsortedSegmentMaxOptions *
+ builtin_options_as_UnsortedSegmentMaxOptions() const
+ {
+ return builtin_options_type() == onert_tflite::BuiltinOptions_UnsortedSegmentMaxOptions
+ ? static_cast<const onert_tflite::UnsortedSegmentMaxOptions *>(builtin_options())
+ : nullptr;
+ }
+ const onert_tflite::UnsortedSegmentSumOptions *
+ builtin_options_as_UnsortedSegmentSumOptions() const
+ {
+ return builtin_options_type() == onert_tflite::BuiltinOptions_UnsortedSegmentSumOptions
+ ? static_cast<const onert_tflite::UnsortedSegmentSumOptions *>(builtin_options())
+ : nullptr;
+ }
+ const onert_tflite::ATan2Options *builtin_options_as_ATan2Options() const
+ {
+ return builtin_options_type() == onert_tflite::BuiltinOptions_ATan2Options
+ ? static_cast<const onert_tflite::ATan2Options *>(builtin_options())
+ : nullptr;
+ }
const flatbuffers::Vector<uint8_t> *custom_options() const
{
return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_CUSTOM_OPTIONS);
@@ -10004,6 +10429,55 @@ Operator::builtin_options_as<onert_tflite::RandomOptions>() const
return builtin_options_as_RandomOptions();
}
+template <>
+inline const onert_tflite::BucketizeOptions *
+Operator::builtin_options_as<onert_tflite::BucketizeOptions>() const
+{
+ return builtin_options_as_BucketizeOptions();
+}
+
+template <>
+inline const onert_tflite::GeluOptions *
+Operator::builtin_options_as<onert_tflite::GeluOptions>() const
+{
+ return builtin_options_as_GeluOptions();
+}
+
+template <>
+inline const onert_tflite::DynamicUpdateSliceOptions *
+Operator::builtin_options_as<onert_tflite::DynamicUpdateSliceOptions>() const
+{
+ return builtin_options_as_DynamicUpdateSliceOptions();
+}
+
+template <>
+inline const onert_tflite::UnsortedSegmentProdOptions *
+Operator::builtin_options_as<onert_tflite::UnsortedSegmentProdOptions>() const
+{
+ return builtin_options_as_UnsortedSegmentProdOptions();
+}
+
+template <>
+inline const onert_tflite::UnsortedSegmentMaxOptions *
+Operator::builtin_options_as<onert_tflite::UnsortedSegmentMaxOptions>() const
+{
+ return builtin_options_as_UnsortedSegmentMaxOptions();
+}
+
+template <>
+inline const onert_tflite::UnsortedSegmentSumOptions *
+Operator::builtin_options_as<onert_tflite::UnsortedSegmentSumOptions>() const
+{
+ return builtin_options_as_UnsortedSegmentSumOptions();
+}
+
+template <>
+inline const onert_tflite::ATan2Options *
+Operator::builtin_options_as<onert_tflite::ATan2Options>() const
+{
+ return builtin_options_as_ATan2Options();
+}
+
struct OperatorBuilder
{
typedef Operator Table;
@@ -11351,6 +11825,41 @@ inline bool VerifyBuiltinOptions(flatbuffers::Verifier &verifier, const void *ob
auto ptr = reinterpret_cast<const onert_tflite::RandomOptions *>(obj);
return verifier.VerifyTable(ptr);
}
+ case BuiltinOptions_BucketizeOptions:
+ {
+ auto ptr = reinterpret_cast<const onert_tflite::BucketizeOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_GeluOptions:
+ {
+ auto ptr = reinterpret_cast<const onert_tflite::GeluOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_DynamicUpdateSliceOptions:
+ {
+ auto ptr = reinterpret_cast<const onert_tflite::DynamicUpdateSliceOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_UnsortedSegmentProdOptions:
+ {
+ auto ptr = reinterpret_cast<const onert_tflite::UnsortedSegmentProdOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_UnsortedSegmentMaxOptions:
+ {
+ auto ptr = reinterpret_cast<const onert_tflite::UnsortedSegmentMaxOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_UnsortedSegmentSumOptions:
+ {
+ auto ptr = reinterpret_cast<const onert_tflite::UnsortedSegmentSumOptions *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
+ case BuiltinOptions_ATan2Options:
+ {
+ auto ptr = reinterpret_cast<const onert_tflite::ATan2Options *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
default:
return true;
}
diff --git a/runtime/onert/frontend/tflite/tflite_schema.fbs b/runtime/onert/frontend/tflite/tflite_schema.fbs
index 9bffb4f3c..f7997528e 100644
--- a/runtime/onert/frontend/tflite/tflite_schema.fbs
+++ b/runtime/onert/frontend/tflite/tflite_schema.fbs
@@ -18,6 +18,10 @@
// Version 1: Add subgraphs to schema.
// Version 2: Rename operators to conform to NN API.
// Version 3: Move buffer data from Model.Subgraph.Tensors to Model.Buffers.
+// Version 3a: Add new builtin op code field. Has backward compatibility with
+// version 3.
+// Version 3b: Rename fields in SignatureDef. Has backward compatibility with
+// version 3 and 3a.
// Change namespace to onert_tflite
namespace onert_tflite;
@@ -43,6 +47,15 @@ enum TensorType : byte {
COMPLEX64 = 8,
INT8 = 9,
FLOAT64 = 10,
+ COMPLEX128 = 11,
+ UINT64 = 12,
+ // Experimental: Resource and variant types are experimental, that are subject
+ // to change. Do not implement custom kernels using resource & variant types
+ // now.
+ RESOURCE = 13,
+ VARIANT = 14,
+ UINT32 = 15,
+ UINT16 = 16
}
// Custom quantization parameters for experimenting with new quantization
@@ -209,14 +222,18 @@ table Tensor {
// Encodes `shape` with unknown dimensions. Unknown dimensions are
// represented with -1.
shape_signature:[int]; // Optional.
+
+ // If false, the rank or the number of tensor dimensions is unknown.
+ // If false, "shape" must be [].
+ has_rank: bool = false;
}
// A list of builtin operators. Builtin operators are slightly faster than custom
// ones, but not by much. Moreover, while custom operators accept an opaque
// object containing configuration parameters, builtins have a predetermined
// set of acceptable options.
-
-enum BuiltinOperator : byte {
+// LINT.IfChange
+enum BuiltinOperator : int32 {
ADD = 0,
AVERAGE_POOL_2D = 1,
CONCATENATION = 2,
@@ -249,7 +266,6 @@ enum BuiltinOperator : byte {
SPACE_TO_DEPTH = 26,
SVDF = 27,
TANH = 28,
- // TODO(aselle): Consider rename to CONCATENATE_EMBEDDINGS
CONCAT_EMBEDDINGS = 29,
SKIP_GRAM = 30,
CALL = 31,
@@ -350,9 +366,39 @@ enum BuiltinOperator : byte {
SELECT_V2 = 123,
DENSIFY = 124,
SEGMENT_SUM = 125,
- BATCH_MATMUL = 126
-}
-
+ BATCH_MATMUL = 126,
+ PLACEHOLDER_FOR_GREATER_OP_CODES = 127,
+ CUMSUM = 128,
+ CALL_ONCE = 129,
+ BROADCAST_TO = 130,
+ RFFT2D = 131,
+ CONV_3D = 132,
+ IMAG=133,
+ REAL=134,
+ COMPLEX_ABS=135,
+ HASHTABLE = 136,
+ HASHTABLE_FIND = 137,
+ HASHTABLE_IMPORT = 138,
+ HASHTABLE_SIZE = 139,
+ REDUCE_ALL = 140,
+ CONV_3D_TRANSPOSE = 141,
+ VAR_HANDLE = 142,
+ READ_VARIABLE = 143,
+ ASSIGN_VARIABLE = 144,
+ BROADCAST_ARGS = 145,
+ RANDOM_STANDARD_NORMAL = 146,
+ BUCKETIZE = 147,
+ RANDOM_UNIFORM = 148,
+ MULTINOMIAL = 149,
+ GELU = 150,
+ DYNAMIC_UPDATE_SLICE = 151,
+ RELU_0_TO_1 = 152,
+ UNSORTED_SEGMENT_PROD = 153,
+ UNSORTED_SEGMENT_MAX = 154,
+ UNSORTED_SEGMENT_SUM = 155,
+ ATAN2 = 156
+}
+// LINT.ThenChange(nnapi_linter/linter.proto)
// Options for the builtin operators.
union BuiltinOptions {
@@ -456,11 +502,34 @@ union BuiltinOptions {
SelectV2Options,
DensifyOptions,
SegmentSumOptions,
- BatchMatMulOptions
-}
-
+ BatchMatMulOptions,
+ CumsumOptions,
+ CallOnceOptions,
+ BroadcastToOptions,
+ Rfft2dOptions,
+ Conv3DOptions,
+ HashtableOptions,
+ HashtableFindOptions,
+ HashtableImportOptions,
+ HashtableSizeOptions,
+ VarHandleOptions,
+ ReadVariableOptions,
+ AssignVariableOptions,
+ RandomOptions,
+ BucketizeOptions,
+ GeluOptions,
+ DynamicUpdateSliceOptions,
+ UnsortedSegmentProdOptions,
+ UnsortedSegmentMaxOptions,
+ UnsortedSegmentSumOptions,
+ ATan2Options
+}
+
+// LINT.IfChange
enum Padding : byte { SAME, VALID }
+// LINT.ThenChange(//tensorflow/compiler/mlir/lite/ir/tfl_op_enums.td)
+// LINT.IfChange
enum ActivationFunctionType : byte {
NONE = 0,
RELU = 1,
@@ -469,6 +538,7 @@ enum ActivationFunctionType : byte {
TANH = 4,
SIGN_BIT = 5,
}
+// LINT.ThenChange(//tensorflow/compiler/mlir/lite/ir/tfl_op_enums.td)
table Conv2DOptions {
padding:Padding;
@@ -479,6 +549,18 @@ table Conv2DOptions {
dilation_h_factor:int = 1;
}
+// Options for both Conv3D and Conv3DTranspose.
+table Conv3DOptions {
+ padding:Padding;
+ stride_d:int;
+ stride_w:int;
+ stride_h:int;
+ fused_activation_function:ActivationFunctionType;
+ dilation_d_factor:int = 1;
+ dilation_w_factor:int = 1;
+ dilation_h_factor:int = 1;
+}
+
table Pool2DOptions {
padding:Padding;
stride_w:int;
@@ -548,10 +630,12 @@ table BidirectionalSequenceRNNOptions {
asymmetric_quantize_inputs:bool;
}
+// LINT.IfChange
enum FullyConnectedOptionsWeightsFormat: byte {
DEFAULT = 0,
SHUFFLED4x16INT8 = 1,
}
+// LINT.ThenChange(//tensorflow/compiler/mlir/lite/ir/tfl_op_enums.td)
// An implementation of TensorFlow fully_connected (a.k.a Dense) layer.
table FullyConnectedOptions {
@@ -584,6 +668,8 @@ table ConcatenationOptions {
table AddOptions {
fused_activation_function:ActivationFunctionType;
+ // Parameters supported by version 3.
+ pot_scale_int16:bool = true;
}
table MulOptions {
@@ -591,6 +677,7 @@ table MulOptions {
}
table L2NormOptions {
+ // This field is currently ignored in the L2 Norm Op.
fused_activation_function:ActivationFunctionType;
}
@@ -601,12 +688,14 @@ table LocalResponseNormalizationOptions {
beta:float;
}
+// LINT.IfChange
enum LSTMKernelType : byte {
// Full LSTM kernel which supports peephole and projection.
FULL = 0,
// Basic LSTM kernels. Equivalent to TensorFlow BasicLSTMCell.
BASIC = 1,
}
+// LINT.ThenChange(//tensorflow/compiler/mlir/lite/ir/tfl_op_enums.td)
// An implementation of TensorFlow LSTMCell and CoupledInputForgetGateLSTMCell
table LSTMOptions {
@@ -664,6 +753,7 @@ table ResizeBilinearOptions {
table ResizeNearestNeighborOptions {
align_corners: bool;
+ half_pixel_centers: bool;
}
// A call operation options
@@ -704,6 +794,8 @@ table DepthToSpaceOptions {
table SubOptions {
fused_activation_function:ActivationFunctionType;
+ // Parameters supported by version 5
+ pot_scale_int16:bool = true;
}
table DivOptions {
@@ -725,6 +817,8 @@ table EmbeddingLookupSparseOptions {
table GatherOptions {
axis: int;
+ // Parameters for Gather version 5 or above.
+ batch_dims: int = 0;
}
table TransposeOptions {
@@ -901,12 +995,14 @@ table LeakyReluOptions {
table SquaredDifferenceOptions {
}
+// LINT.IfChange
enum MirrorPadMode : byte {
// Doesn't include borders.
REFLECT = 0,
// Includes borders.
SYMMETRIC = 1,
}
+// LINT.ThenChange(//tensorflow/compiler/mlir/lite/ir/tfl_op_enums.td)
table MirrorPadOptions {
mode:MirrorPadMode;
@@ -947,6 +1043,10 @@ table IfOptions {
else_subgraph_index:int;
}
+table CallOnceOptions {
+ init_subgraph_index:int;
+}
+
table WhileOptions {
cond_subgraph_index:int;
body_subgraph_index:int;
@@ -971,19 +1071,100 @@ table SegmentSumOptions {
}
table BatchMatMulOptions {
- adjoint_lhs:bool;
- adjoint_rhs:bool;
+ adj_x:bool;
+ adj_y:bool;
+ // Parameters for BatchMatMul version 4 or above.
+ // If set to true, then weights-only op will use asymmetric quantization for
+ // inputs.
+ asymmetric_quantize_inputs: bool;
+}
+
+table CumsumOptions {
+ exclusive:bool;
+ reverse:bool;
+}
+
+table BroadcastToOptions {
+}
+
+table Rfft2dOptions {
+}
+
+table HashtableOptions {
+ // The identity of hash tables. This identity will be used across different
+ // subgraphs in the same interpreter instance.
+ table_id:int;
+ key_dtype:TensorType;
+ value_dtype:TensorType;
+}
+
+table HashtableFindOptions {
+}
+
+table HashtableImportOptions {
+}
+
+table HashtableSizeOptions {
+}
+
+table VarHandleOptions {
+ container:string;
+ shared_name:string;
}
+table ReadVariableOptions {
+}
+
+table AssignVariableOptions {
+}
+
+table RandomOptions {
+ seed: long;
+ seed2: long;
+}
+
+table BucketizeOptions {
+ boundaries: [float]; // The bucket boundaries.
+}
+
+table GeluOptions {
+ approximate: bool;
+}
+
+table DynamicUpdateSliceOptions {
+}
+
+table UnsortedSegmentProdOptions {
+}
+
+table UnsortedSegmentMaxOptions {
+}
+
+table UnsortedSegmentSumOptions {
+}
+
+table ATan2Options {
+}
+
+
// An OperatorCode can be an enum value (BuiltinOperator) if the operator is a
// builtin, or a string if the operator is custom.
table OperatorCode {
- builtin_code:BuiltinOperator;
+ // This field is for backward compatibility. This field will be used when
+ // the value of the extended builtin_code field has less than
+ // BulitinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES.
+ deprecated_builtin_code:byte;
custom_code:string;
// The version of the operator. The version need to be bumped whenever new
// parameters are introduced into an op.
version:int = 1;
+
+ // This field is introduced for resolving op builtin code shortage problem
+ // (the original BuiltinOperator enum field was represented as a byte).
+ // This field will be used when the value of the extended builtin_code field
+ // has greater than BulitinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES.
+ builtin_code:BuiltinOperator;
}
enum CustomOptionsFormat : byte {
@@ -1062,6 +1243,35 @@ table Metadata {
buffer:uint;
}
+// Map from an alias name of tensor to tensor index in the graph.
+// This is used in Signature def.
+table TensorMap {
+ // Represents the alias to use for this tensor.
+ name:string;
+
+ // The actual tensor index in the primary graph, that 'name' corresponds to.
+ tensor_index:uint;
+}
+
+// This corresponds to SignatureDef in Tensorflow SavedModel.
+// The SignatureDef will be part of the SavedModel provided for conversion.
+table SignatureDef {
+ // Named inputs for this signature.
+ inputs:[TensorMap];
+
+ // Named outputs for this signature.
+ outputs:[TensorMap];
+
+ // Key value which was in the Tensorflow SavedModel SignatureDef map.
+ signature_key:string;
+
+ // Model tag, deprecated.
+ deprecated_tag:string (deprecated);
+
+ // Index of subgraphs that corresponds to the exported method.
+ subgraph_index:uint;
+}
+
table Model {
// Version of the schema.
version:uint;
@@ -1090,6 +1300,9 @@ table Model {
// Metadata about the model.
metadata:[Metadata];
+
+ // Optional SignatureDefs for the model.
+ signature_defs:[SignatureDef];
}
root_type Model;
diff --git a/runtime/onert/odc/CMakeLists.txt b/runtime/onert/odc/CMakeLists.txt
new file mode 100644
index 000000000..e48878dc3
--- /dev/null
+++ b/runtime/onert/odc/CMakeLists.txt
@@ -0,0 +1,39 @@
+# Luci library is not supported is on cross build
+if(CMAKE_CROSSCOMPILING)
+ return()
+endif()
+
+nnfw_find_package(Luci QUIET)
+if(NOT Luci_FOUND)
+ message(STATUS "Luci not found. Skip onert_odc")
+ return()
+endif()
+
+file(GLOB_RECURSE SOURCES "*.cc")
+file(GLOB_RECURSE TESTS "*.test.cc")
+list(REMOVE_ITEM SOURCES ${TESTS})
+
+add_library(onert_odc SHARED ${SOURCES})
+target_link_libraries(onert_odc PRIVATE onert_core luci::import luci::export luci::pass luci::loco)
+target_link_libraries(onert_odc PRIVATE nnfw_common)
+target_link_libraries(onert_odc PRIVATE nnfw_coverage)
+
+install(TARGETS onert_odc LIBRARY DESTINATION lib/nnfw/odc)
+
+if(NOT ENABLE_TEST)
+ return()
+endif(NOT ENABLE_TEST)
+
+# Unit Tests
+set(TEST_ONERT_ODC test_onert_odc)
+
+add_executable(${TEST_ONERT_ODC} ${TESTS})
+
+target_link_libraries(${TEST_ONERT_ODC} onert_odc)
+# Requires linking nnfw_coverage: check header coverage
+target_link_libraries(${TEST_ONERT_CORE} nnfw_coverage)
+target_link_libraries(${TEST_ONERT_ODC} gtest gtest_main dl ${LIB_PTHREAD})
+target_include_directories(${TEST_ONERT_ODC} PRIVATE $<TARGET_PROPERTY:onert_odc,INCLUDE_DIRECTORIES>)
+
+add_test(${TEST_ONERT_ODC} ${TEST_ONERT_ODC})
+install(TARGETS ${TEST_ONERT_ODC} DESTINATION unittest)
diff --git a/runtime/onert/odc/Quantizer.cc b/runtime/onert/odc/Quantizer.cc
new file mode 100644
index 000000000..b8aec97ce
--- /dev/null
+++ b/runtime/onert/odc/Quantizer.cc
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Quantizer.h"
+
+#include <luci/ImporterEx.h>
+#include <luci/CircleQuantizer.h>
+#include <luci/CircleExporter.h>
+#include <luci/CircleFileExpContract.h>
+
+#include <iostream>
+
+extern "C" onert::odc::IQuantizer *create_quantizer() { return new onert::odc::Quantizer(); }
+extern "C" void destroy_quantizer(onert::odc::IQuantizer *quantizer) { delete quantizer; }
+
+namespace onert
+{
+namespace odc
+{
+
+int Quantizer::quantize(const char *in, const char *out, bool is_q16)
+{
+ // Load model from the file
+ luci::ImporterEx importerex;
+ auto module = importerex.importVerifyModule(std::string(in));
+ if (module.get() == nullptr)
+ return 1;
+
+ luci::CircleQuantizer quantizer;
+ auto options = quantizer.options();
+ {
+ options->enable(luci::CircleQuantizer::Options::Algorithm::QuantizeWeights);
+
+ using AlgorithmParameters = luci::CircleQuantizer::Options::AlgorithmParameters;
+ options->param(AlgorithmParameters::Quantize_input_model_dtype, "float32");
+ options->param(AlgorithmParameters::Quantize_output_model_dtype, is_q16 ? "int16" : "int8");
+ options->param(AlgorithmParameters::Quantize_granularity, "channel");
+ }
+
+ for (size_t idx = 0; idx < module->size(); ++idx)
+ {
+ auto graph = module->graph(idx);
+
+ // quantize the graph
+ quantizer.quantize(graph);
+
+ // Skip validate
+ // TODO Validate if needed
+#if 0
+ if (!luci::validate(graph))
+ {
+ std::cerr << "ERROR: Quantized graph is invalid" << std::endl;
+ return 1;
+ }
+#endif
+ }
+
+ // Export to output Circle file
+ luci::CircleExporter exporter;
+ luci::CircleFileExpContract contract(module.get(), std::string(out));
+
+ if (!exporter.invoke(&contract))
+ return 1;
+
+ // Return 0 when luci::CircleQuantizer::Options::Algorithm::QuantizeWeights is ready
+ return 0;
+}
+
+} // namespace odc
+} // namespace onert
diff --git a/runtime/onert/odc/Quantizer.h b/runtime/onert/odc/Quantizer.h
new file mode 100644
index 000000000..8a03f59d5
--- /dev/null
+++ b/runtime/onert/odc/Quantizer.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_ODC_QUANTIZE_H__
+#define __ONERT_ODC_QUANTIZE_H__
+
+#include "odc/IQuantizer.h"
+
+namespace onert
+{
+namespace odc
+{
+
+class Quantizer : public IQuantizer
+{
+public:
+ Quantizer() = default;
+ ~Quantizer() = default;
+
+ int quantize(const char *in, const char *out, bool is_q16);
+};
+
+} // namespace odc
+} // namespace onert
+
+#endif // __ONERT_ODC_QUANTIZE_H__
diff --git a/runtime/onert/odc/Quantizer.test.cc b/runtime/onert/odc/Quantizer.test.cc
new file mode 100644
index 000000000..22baed576
--- /dev/null
+++ b/runtime/onert/odc/Quantizer.test.cc
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Quantizer.h"
+
+#include <gtest/gtest.h>
+
+using namespace onert::odc;
+
+// Test model input path is not set
+TEST(odc_Quantizer, neg_model_input_path)
+{
+ Quantizer quantizer;
+ ASSERT_THROW(quantizer.quantize(nullptr, "out", false), std::logic_error);
+}
+
+// Test model output path is not set
+TEST(odc_Quantizer, neg_model_output_path)
+{
+ Quantizer quantizer;
+ ASSERT_NE(quantizer.quantize("in", nullptr, false), 0);
+}
+
+// Test invalid model input path
+TEST(odc_Quantizer, neg_invalid_model_input_path)
+{
+ Quantizer quantizer;
+ ASSERT_NE(quantizer.quantize("invalid_model_input_path.circle", "out", false), 0);
+}
diff --git a/runtime/service/npud/backend/trix/TrixBackend.cc b/runtime/service/npud/backend/trix/TrixBackend.cc
index 58264e642..38717c13f 100644
--- a/runtime/service/npud/backend/trix/TrixBackend.cc
+++ b/runtime/service/npud/backend/trix/TrixBackend.cc
@@ -118,7 +118,7 @@ NpuStatus TrixBackend::destroyContext(NpuContext *ctx)
npudev_h handle = _dev->handles.at(ctx->defaultCore);
- for (auto rid : ctx->requests)
+ for (auto &&rid : ctx->requests)
{
if (removeNPU_request(handle, rid) < 0)
{
@@ -127,7 +127,7 @@ NpuStatus TrixBackend::destroyContext(NpuContext *ctx)
_dev->requests.erase(rid);
}
- for (auto mid : ctx->models)
+ for (auto &&mid : ctx->models)
{
auto &minfo = _dev->models.at(mid);
if (--minfo->refCount == 0)
diff --git a/runtime/service/npud/core/Backend.h b/runtime/service/npud/core/Backend.h
index 5bc13b66c..6b810d18e 100644
--- a/runtime/service/npud/core/Backend.h
+++ b/runtime/service/npud/core/Backend.h
@@ -20,6 +20,7 @@
#include "ir/Layout.h"
#include "ir/DataType.h"
+#include <cstdint>
#include <string>
#include <vector>
diff --git a/tests/nnfw_api/src/CircleGen.cc b/tests/nnfw_api/src/CircleGen.cc
index 4f1c7f9f5..e4601843c 100644
--- a/tests/nnfw_api/src/CircleGen.cc
+++ b/tests/nnfw_api/src/CircleGen.cc
@@ -624,7 +624,7 @@ uint32_t CircleGen::addCustomOperatorCode(std::string custom_code)
flatbuffers::Offset<circle::Buffer> CircleGen::buildBuffer(const uint8_t *buf, size_t size)
{
- if (buf == nullptr && size == 0)
+ if (buf == nullptr || size == 0)
return circle::CreateBuffer(_fbb);
auto buffer = _fbb.CreateVector(buf, size);
return circle::CreateBuffer(_fbb, buffer);
diff --git a/tests/nnfw_api/src/one_op_tests/Conv2D.test.cc b/tests/nnfw_api/src/one_op_tests/Conv2D.test.cc
index dccf2e5b8..46632f18d 100644
--- a/tests/nnfw_api/src/one_op_tests/Conv2D.test.cc
+++ b/tests/nnfw_api/src/one_op_tests/Conv2D.test.cc
@@ -166,6 +166,31 @@ TEST_F(GenModelTest, OneOp_Conv2D_U8_PerChannel)
SUCCEED();
}
+TEST_F(GenModelTest, OneOp_Conv2D_I8_Hybrid_PerChannel)
+{
+ CircleGen cgen;
+ std::vector<int8_t> weight_data{1, 2, 3, 1, 2, 3, 7, 8, 9};
+ uint32_t weight_buf = cgen.addBuffer(weight_data);
+ std::vector<float> bias_data{0, 0, 0};
+ uint32_t bias_buf = cgen.addBuffer(bias_data);
+ int in = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_FLOAT32});
+ std::vector<float> weight_scales = {0.5, 1, 0.5};
+ std::vector<int64_t> weight_zeropoints = {0, 0, 0};
+ int weight = cgen.addTensor({{3, 1, 1, 3}, circle::TensorType::TensorType_INT8, weight_buf},
+ weight_scales, weight_zeropoints);
+ int bias = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+ int out = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_FLOAT32});
+ cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1,
+ circle::ActivationFunctionType_NONE);
+ cgen.setInputsAndOutputs({in}, {out});
+
+ _context = std::make_unique<GenModelTestContext>(cgen.finish());
+ _context->addTestCase(uniformTCD<float>({{5, 5, 5}}, {{15, 30, 60}}));
+ _context->setBackends({"cpu"});
+
+ SUCCEED();
+}
+
TEST_F(GenModelTest, neg_OneOp_Conv2D_Type)
{
CircleGen cgen;
@@ -276,3 +301,29 @@ TEST_F(GenModelTest, neg_OneOp_Conv2D_I8_NonZero_ZeroPoints)
SUCCEED();
}
+
+TEST_F(GenModelTest, neg_OneOp_Conv2D_I8_Hybrid_PerTensor)
+{
+ CircleGen cgen;
+ std::vector<int8_t> weight_data{1, 2, 3, 4, 5, 6, 7, 8, 9};
+ uint32_t weight_buf = cgen.addBuffer(weight_data);
+ std::vector<float> bias_data{0, 2, 4};
+ uint32_t bias_buf = cgen.addBuffer(bias_data);
+ int in = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_FLOAT32});
+ // Hybrid does not support per-tensor.
+ std::vector<float> weight_scales = {0.5};
+ std::vector<int64_t> weight_zeropoints = {0};
+ int weight = cgen.addTensor({{3, 1, 1, 3}, circle::TensorType::TensorType_INT8, weight_buf},
+ weight_scales, weight_zeropoints);
+ int bias = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+ int out = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_FLOAT32});
+ cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1,
+ circle::ActivationFunctionType_NONE);
+ cgen.setInputsAndOutputs({in}, {out});
+
+ _context = std::make_unique<GenModelTestContext>(cgen.finish());
+ _context->setBackends({"cpu"});
+ _context->expectFailCompile();
+
+ SUCCEED();
+}
diff --git a/tests/nnfw_api/src/one_op_tests/DepthwiseConv2D.test.cc b/tests/nnfw_api/src/one_op_tests/DepthwiseConv2D.test.cc
index f82d988d5..55f43dcaf 100644
--- a/tests/nnfw_api/src/one_op_tests/DepthwiseConv2D.test.cc
+++ b/tests/nnfw_api/src/one_op_tests/DepthwiseConv2D.test.cc
@@ -203,6 +203,45 @@ TEST_F(GenModelTest, OneOp_DepthwiseConv2D_U8_PerChannel)
SUCCEED();
}
+TEST_F(GenModelTest, OneOp_DepthwiseConv2D_I8_Hybrid_PerChannel)
+{
+ CircleGen cgen;
+ // weight
+ // clang-format off
+ std::vector<int8_t> weight_data{1, 2, 1, 2, -9, 10, -9, 10,
+ 5, 6, 5, 6, 13, -14, 13, -14};
+ // clang-format on
+ uint32_t weight_buf = cgen.addBuffer(weight_data);
+ std::vector<float> weight_scales = {1, 1, 1, 1};
+ std::vector<int64_t> weight_zeropoints = {0, 0, 0, 0};
+ int weight = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_INT8, weight_buf},
+ weight_scales, weight_zeropoints);
+ // bias
+ std::vector<float> bias_data{0, 1, 2, 3};
+ uint32_t bias_buf = cgen.addBuffer(bias_data);
+ int bias = cgen.addTensor({{1, 1, 1, 4}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+
+ // in and out
+ int in = cgen.addTensor({{1, 3, 2, 2}, circle::TensorType::TensorType_FLOAT32});
+ int out = cgen.addTensor({{1, 2, 1, 4}, circle::TensorType::TensorType_FLOAT32});
+
+ cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1, 2,
+ circle::ActivationFunctionType_NONE);
+ cgen.setInputsAndOutputs({in}, {out});
+
+ _context = std::make_unique<GenModelTestContext>(cgen.finish());
+ // clang-format off
+ _context->addTestCase(uniformTCD<float>({{0, 1, 2, 3,
+ 0, 1, 2, 3,
+ 0, 1, 2, 3}},
+ {{8, -7, 20, -1,
+ 8, -7, 20, -1}}));
+ // clang-format on
+ _context->setBackends({"cpu"});
+
+ SUCCEED();
+}
+
TEST_F(GenModelTest, neg_OneOp_DepthwiseConv2D_Stride)
{
CircleGen cgen;
@@ -500,3 +539,29 @@ TEST_F(GenModelTest, neg_OneOp_DepthwiseConv2D_I8_NonZero_ZeroPoints)
SUCCEED();
}
+
+TEST_F(GenModelTest, neg_OneOp_DepthwiseConv2D_I8_Hybrid_PerTensor)
+{
+ // PerTensor Quantized Weight is not supported
+ CircleGen cgen;
+ std::vector<int8_t> weight_data{1, 2, 3};
+ uint32_t weight_buf = cgen.addBuffer(weight_data);
+ std::vector<float> bias_data{0, 2, 4};
+ uint32_t bias_buf = cgen.addBuffer(bias_data);
+ int in = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_FLOAT32});
+ // Hybrid does not support per-tensor.
+ std::vector<float> weight_scales = {0.5};
+ std::vector<int64_t> weight_zeropoints = {0};
+ int weight = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT8, weight_buf},
+ weight_scales, weight_zeropoints);
+ int bias = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+ int out = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_FLOAT32});
+ cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1,
+ /* depth_multiplier */ 1, circle::ActivationFunctionType_NONE);
+ cgen.setInputsAndOutputs({in}, {out});
+
+ _context = std::make_unique<GenModelTestContext>(cgen.finish());
+ _context->expectFailCompile();
+ _context->setBackends({"cpu"});
+ SUCCEED();
+}
diff --git a/tests/tools/onert_run/src/args.cc b/tests/tools/onert_run/src/args.cc
index 1e9d1aa69..a64d81db5 100644
--- a/tests/tools/onert_run/src/args.cc
+++ b/tests/tools/onert_run/src/args.cc
@@ -299,6 +299,10 @@ void Args::Initialize(void)
"0: prints the only result. Messages btw run don't print\n"
"1: prints result and message btw run\n"
"2: prints all of messages to print\n")
+ ("quantize,q", po::value<std::string>()->default_value("")->notifier([&](const auto &v) { _quantize = v; }), "Request quantization with type (int8 or int16)")
+ ("qpath", po::value<std::string>()->default_value("")->notifier([&](const auto &v) { _quantized_model_path = v; }),
+ "Path to export quantized model.\n"
+ "If it is not set, the quantized model will be exported to the same directory of the original model/package with q8/q16 suffix.")
;
// clang-format on
diff --git a/tests/tools/onert_run/src/args.h b/tests/tools/onert_run/src/args.h
index e35a761ed..97d9b1af1 100644
--- a/tests/tools/onert_run/src/args.h
+++ b/tests/tools/onert_run/src/args.h
@@ -69,6 +69,8 @@ public:
/// @brief Return true if "--shape_run" or "--shape_prepare" is provided
bool shapeParamProvided();
const int getVerboseLevel(void) const { return _verbose_level; }
+ const std::string &getQuantize(void) const { return _quantize; }
+ const std::string &getQuantizedModelPath(void) const { return _quantized_model_path; }
private:
void Initialize();
@@ -99,6 +101,8 @@ private:
bool _print_version = false;
int _verbose_level;
bool _use_single_model = false;
+ std::string _quantize;
+ std::string _quantized_model_path;
};
} // end of namespace onert_run
diff --git a/tests/tools/onert_run/src/onert_run.cc b/tests/tools/onert_run/src/onert_run.cc
index 5acb2bb64..0bc64bb2b 100644
--- a/tests/tools/onert_run/src/onert_run.cc
+++ b/tests/tools/onert_run/src/onert_run.cc
@@ -23,6 +23,7 @@
#include "nnfw.h"
#include "nnfw_util.h"
#include "nnfw_internal.h"
+#include "nnfw_experimental.h"
#include "randomgen.h"
#include "rawformatter.h"
#ifdef RUY_PROFILER
@@ -48,6 +49,33 @@ void overwriteShapeMap(onert_run::TensorShapeMap &shape_map,
shape_map[i] = shapes[i];
}
+std::string genQuantizedModelPathFromModelPath(const std::string &model_path, bool is_q16)
+{
+ auto const extension_pos = model_path.find(".circle");
+ if (extension_pos == std::string::npos)
+ {
+ std::cerr << "Input model isn't .circle." << std::endl;
+ exit(-1);
+ }
+ auto const qstring = std::string("_quantized_") + (is_q16 ? "q16" : "q8");
+ return model_path.substr(0, extension_pos) + qstring + ".circle";
+}
+
+std::string genQuantizedModelPathFromPackagePath(const std::string &package_path, bool is_q16)
+{
+ auto package_path_without_slash = package_path;
+ if (package_path_without_slash.back() == '/')
+ package_path_without_slash.pop_back();
+ auto package_name_pos = package_path_without_slash.find_last_of('/');
+ if (package_name_pos == std::string::npos)
+ package_name_pos = 0;
+ else
+ package_name_pos++;
+ auto package_name = package_path_without_slash.substr(package_name_pos);
+ auto const qstring = std::string("_quantized_") + (is_q16 ? "q16" : "q8");
+ return package_path_without_slash + "/" + package_name + qstring + ".circle";
+}
+
int main(const int argc, char **argv)
{
using namespace onert_run;
@@ -85,6 +113,37 @@ int main(const int argc, char **argv)
NNPR_ENSURE_STATUS(nnfw_load_model_from_file(session, args.getPackageFilename().c_str()));
});
+ // Quantize model
+ auto quantize = args.getQuantize();
+ if (!quantize.empty())
+ {
+ NNFW_QUANTIZE_TYPE quantize_type = NNFW_QUANTIZE_TYPE_NOT_SET;
+ if (quantize == "int8")
+ quantize_type = NNFW_QUANTIZE_TYPE_U8_ASYM;
+ if (quantize == "int16")
+ quantize_type = NNFW_QUANTIZE_TYPE_I16_SYM;
+ NNPR_ENSURE_STATUS(nnfw_set_quantization_type(session, quantize_type));
+
+ if (args.getQuantizedModelPath() != "")
+ NNPR_ENSURE_STATUS(
+ nnfw_set_quantized_model_path(session, args.getQuantizedModelPath().c_str()));
+ else
+ {
+ if (args.useSingleModel())
+ NNPR_ENSURE_STATUS(nnfw_set_quantized_model_path(
+ session,
+ genQuantizedModelPathFromModelPath(args.getModelFilename(), quantize == "int16")
+ .c_str()));
+ else
+ NNPR_ENSURE_STATUS(nnfw_set_quantized_model_path(
+ session,
+ genQuantizedModelPathFromPackagePath(args.getPackageFilename(), quantize == "int16")
+ .c_str()));
+ }
+
+ NNPR_ENSURE_STATUS(nnfw_quantize(session));
+ }
+
char *available_backends = std::getenv("BACKENDS");
if (available_backends)
NNPR_ENSURE_STATUS(nnfw_set_available_backends(session, available_backends));
diff --git a/tests/tools/onert_train/CMakeLists.txt b/tests/tools/onert_train/CMakeLists.txt
new file mode 100644
index 000000000..f047b2ad0
--- /dev/null
+++ b/tests/tools/onert_train/CMakeLists.txt
@@ -0,0 +1,60 @@
+if(NOT BUILD_ONERT_TRAIN)
+ return()
+endif(NOT BUILD_ONERT_TRAIN)
+
+if(NOT BUILD_ONERT)
+ return()
+endif(NOT BUILD_ONERT)
+
+list(APPEND ONERT_TRAIN_SRCS "src/onert_train.cc")
+list(APPEND ONERT_TRAIN_SRCS "src/args.cc")
+list(APPEND ONERT_TRAIN_SRCS "src/nnfw_util.cc")
+list(APPEND ONERT_TRAIN_SRCS "src/randomgen.cc")
+list(APPEND ONERT_TRAIN_SRCS "src/rawformatter.cc")
+list(APPEND ONERT_TRAIN_SRCS "src/rawdataloader.cc")
+
+nnfw_find_package(Boost REQUIRED program_options)
+nnfw_find_package(HDF5 QUIET)
+
+if (HDF5_FOUND)
+ list(APPEND ONERT_TRAIN_SRCS "src/h5formatter.cc")
+endif()
+
+add_executable(onert_train ${ONERT_TRAIN_SRCS})
+
+if (HDF5_FOUND)
+ target_compile_definitions(onert_train PRIVATE ONERT_HAVE_HDF5=1)
+ target_include_directories(onert_train PRIVATE ${HDF5_INCLUDE_DIRS})
+ target_link_libraries(onert_train ${HDF5_CXX_LIBRARIES})
+else()
+ message(WARNING "HDF5 NOT found. Install libhdf5-dev or set EXT_HDF5_DIR to support load/dump in onert_train.")
+endif(HDF5_FOUND)
+
+target_include_directories(onert_train PRIVATE src)
+target_include_directories(onert_train PRIVATE ${Boost_INCLUDE_DIRS})
+
+target_link_libraries(onert_train nnfw_lib_tflite jsoncpp)
+target_link_libraries(onert_train nnfw-dev)
+target_link_libraries(onert_train ${Boost_PROGRAM_OPTIONS_LIBRARY})
+target_link_libraries(onert_train nnfw_lib_benchmark)
+
+install(TARGETS onert_train DESTINATION bin)
+
+if(NOT ENABLE_TEST)
+ return()
+endif(NOT ENABLE_TEST)
+
+# Unit Tests
+set(TEST_ONERT_TRAIN test_onert_train)
+
+file(GLOB_RECURSE ONERT_TRAIN_TEST_SRCS "test/*.cc")
+list(APPEND ONERT_TRAIN_TEST_SRCS "src/rawdataloader.cc")
+list(APPEND ONERT_TRAIN_TEST_SRCS "src/nnfw_util.cc")
+
+add_executable(${TEST_ONERT_TRAIN} ${ONERT_TRAIN_TEST_SRCS})
+
+target_link_libraries(${TEST_ONERT_TRAIN} nnfw-dev)
+target_link_libraries(${TEST_ONERT_TRAIN} gtest gtest_main dl ${LIB_PTHREAD})
+
+add_test(${TEST_ONERT_TRAIN} ${TEST_ONERT_TRAIN})
+install(TARGETS ${TEST_ONERT_TRAIN} DESTINATION unittest)
diff --git a/tests/tools/onert_train/README.md b/tests/tools/onert_train/README.md
new file mode 100644
index 000000000..a201237f6
--- /dev/null
+++ b/tests/tools/onert_train/README.md
@@ -0,0 +1,13 @@
+# onert_train
+
+`onert_train` aims to train ai model. This tool trains given the ai model entered by the user using a given input and an expected output, and stores or inference the trained model.
+
+The input models that can be supported by this tool are as follows.
+- circle
+- nnpackage
+
+## Usage
+
+### Simple train
+
+### Simple inference to trained model
diff --git a/tests/tools/onert_train/src/allocation.h b/tests/tools/onert_train/src/allocation.h
new file mode 100644
index 000000000..f5a6aa73b
--- /dev/null
+++ b/tests/tools/onert_train/src/allocation.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_TRAIN_ALLOCATION_H__
+#define __ONERT_TRAIN_ALLOCATION_H__
+
+#include <cstdlib>
+#include <cstdint>
+
+namespace onert_train
+{
+class Allocation
+{
+public:
+ Allocation() : data_(nullptr) {}
+ ~Allocation() { free(data_); }
+ void *data() const { return data_; }
+ void *alloc(uint64_t sz)
+ {
+ if (data_)
+ {
+ free(data_);
+ }
+
+ return data_ = malloc(sz);
+ }
+
+private:
+ void *data_;
+};
+} // namespace onert_train
+
+#endif // __ONERT_TRAIN_ALLOCATION_H__
diff --git a/tests/tools/onert_train/src/args.cc b/tests/tools/onert_train/src/args.cc
new file mode 100644
index 000000000..dbdd384b5
--- /dev/null
+++ b/tests/tools/onert_train/src/args.cc
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "args.h"
+
+#include <functional>
+#include <iostream>
+#include <sys/stat.h>
+#include <json/json.h>
+
+namespace
+{
+
+// This function parses a json object and returns as a vector of integers
+// For example,
+// [0, [1, 2, 3, 4], 3, 40, 4, []] in JSON
+// is converted to:
+// {
+// 0 -> [1, 2, 3, 4]
+// 3 -> 40
+// 4 -> []
+// } in std::unordered_map. Note that the value type is still Json::Value.
+std::unordered_map<uint32_t, Json::Value> argArrayToMap(const Json::Value &jsonval)
+{
+ if (!jsonval.isArray() || (jsonval.size() % 2 != 0))
+ {
+ std::cerr << "JSON argument must be an even-sized array in JSON\n";
+ exit(1);
+ }
+
+ std::unordered_map<uint32_t, Json::Value> ret;
+ for (uint32_t i = 0; i < jsonval.size(); i += 2)
+ {
+ if (!jsonval[i].isUInt())
+ {
+ std::cerr << "Key values(values in even indices) must be unsigned integers\n";
+ exit(1);
+ }
+ uint32_t key = jsonval[i].asUInt();
+ Json::Value val = jsonval[i + 1];
+ ret[key] = jsonval[i + 1];
+ }
+ return ret;
+}
+
+void checkModelfile(const std::string &model_filename)
+{
+ if (model_filename.empty())
+ {
+ // TODO Print usage instead of the below message
+ std::cerr << "Please specify model file. Run with `--help` for usage."
+ << "\n";
+
+ exit(1);
+ }
+ else
+ {
+ if (access(model_filename.c_str(), F_OK) == -1)
+ {
+ std::cerr << "Model file not found: " << model_filename << "\n";
+ exit(1);
+ }
+ }
+}
+
+void checkPackage(const std::string &package_filename)
+{
+ if (package_filename.empty())
+ {
+ // TODO Print usage instead of the below message
+ std::cerr << "Please specify nnpackage file. Run with `--help` for usage."
+ << "\n";
+
+ exit(1);
+ }
+ else
+ {
+ if (access(package_filename.c_str(), F_OK) == -1)
+ {
+ std::cerr << "nnpackage not found: " << package_filename << "\n";
+ exit(1);
+ }
+ }
+}
+
+} // namespace
+
+namespace onert_train
+{
+
+Args::Args(const int argc, char **argv)
+{
+ Initialize();
+ Parse(argc, argv);
+}
+
+void Args::Initialize(void)
+{
+ auto process_nnpackage = [&](const std::string &package_filename) {
+ _package_filename = package_filename;
+
+ std::cerr << "Package Filename " << _package_filename << std::endl;
+ checkPackage(package_filename);
+ };
+
+ auto process_modelfile = [&](const std::string &model_filename) {
+ _model_filename = model_filename;
+
+ std::cerr << "Model Filename " << _model_filename << std::endl;
+ checkModelfile(model_filename);
+
+ _use_single_model = true;
+ };
+
+ auto process_path = [&](const std::string &path) {
+ struct stat sb;
+ if (stat(path.c_str(), &sb) == 0)
+ {
+ if (sb.st_mode & S_IFDIR)
+ {
+ _package_filename = path;
+ checkPackage(path);
+ std::cerr << "Package Filename " << path << std::endl;
+ }
+ else
+ {
+ _model_filename = path;
+ checkModelfile(path);
+ std::cerr << "Model Filename " << path << std::endl;
+ _use_single_model = true;
+ }
+ }
+ else
+ {
+ std::cerr << "Cannot find: " << path << "\n";
+ exit(1);
+ }
+ };
+
+ auto process_load_raw_inputfile = [&](const std::string &input_filename) {
+ _load_raw_input_filename = input_filename;
+
+ std::cerr << "Model Input Filename " << _load_raw_input_filename << std::endl;
+ checkModelfile(_load_raw_input_filename);
+ };
+
+ auto process_load_raw_expectedfile = [&](const std::string &expected_filename) {
+ _load_raw_expected_filename = expected_filename;
+
+ std::cerr << "Model Expected Filename " << _load_raw_expected_filename << std::endl;
+ checkModelfile(_load_raw_expected_filename);
+ };
+
+ auto process_output_sizes = [&](const std::string &output_sizes_json_str) {
+ Json::Value root;
+ Json::Reader reader;
+ if (!reader.parse(output_sizes_json_str, root, false))
+ {
+ std::cerr << "Invalid JSON format for output_sizes \"" << output_sizes_json_str << "\"\n";
+ exit(1);
+ }
+
+ auto arg_map = argArrayToMap(root);
+ for (auto &pair : arg_map)
+ {
+ uint32_t key = pair.first;
+ Json::Value &val_json = pair.second;
+ if (!val_json.isUInt())
+ {
+ std::cerr << "All the values in `output_sizes` must be unsigned integers\n";
+ exit(1);
+ }
+ uint32_t val = val_json.asUInt();
+ _output_sizes[key] = val;
+ }
+ };
+
+ // General options
+ po::options_description general("General options", 100);
+
+ // clang-format off
+ general.add_options()
+ ("help,h", "Print available options")
+ ("version", "Print version and exit immediately")
+ ("nnpackage", po::value<std::string>()->notifier(process_nnpackage), "NN Package file(directory) name")
+ ("modelfile", po::value<std::string>()->notifier(process_modelfile), "NN Model filename")
+ ("path", po::value<std::string>()->notifier(process_path), "NN Package or NN Modelfile path")
+ ("data_length", po::value<int>()->default_value(-1)->notifier([&](const auto &v) { _data_length = v; }), "Data length number")
+ ("load_input:raw", po::value<std::string>()->notifier(process_load_raw_inputfile),
+ "NN Model Raw Input data file\n"
+ "The datafile must have data for each input number.\n"
+ "If there are 3 inputs, the data of input0 must exist as much as data_length, "
+ "and the data for input1 and input2 must be held sequentially as data_length.\n"
+ )
+ ("load_expected:raw", po::value<std::string>()->notifier(process_load_raw_expectedfile),
+ "NN Model Raw Expected data file\n"
+ "(Same data policy with load_input:raw)\n"
+ )
+ ("mem_poll,m", po::value<bool>()->default_value(false)->notifier([&](const auto &v) { _mem_poll = v; }), "Check memory polling")
+ ("epoch", po::value<int>()->default_value(5)->notifier([&](const auto &v) { _epoch = v; }), "Epoch number (default: 5)")
+ ("batch_size", po::value<int>()->default_value(32)->notifier([&](const auto &v) { _batch_size = v; }), "Batch size (default: 32)")
+ ("learning_rate", po::value<float>()->default_value(1.0e-4)->notifier([&](const auto &v) { _learning_rate = v; }), "Learning rate (default: 1.0e-4)")
+ ("loss", po::value<int>()->default_value(0)->notifier([&] (const auto &v) { _loss_type = v; }),
+ "Loss type\n"
+ "0: MEAN_SQUARED_ERROR (default)\n"
+ "1: CATEGORICAL_CROSSENTROPY\n")
+ ("optimizer", po::value<int>()->default_value(0)->notifier([&] (const auto &v) { _optimizer_type = v; }),
+ "Optimizer type\n"
+ "0: SGD (default)\n"
+ "1: Adam\n")
+ ("verbose_level,v", po::value<int>()->default_value(0)->notifier([&](const auto &v) { _verbose_level = v; }),
+ "Verbose level\n"
+ "0: prints the only result. Messages btw run don't print\n"
+ "1: prints result and message btw run\n"
+ "2: prints all of messages to print\n")
+ ("output_sizes", po::value<std::string>()->notifier(process_output_sizes),
+ "The output buffer size in JSON 1D array\n"
+ "If not given, the model's output sizes are used\n"
+ "e.g. '[0, 40, 2, 80]' to set 0th tensor to 40 and 2nd tensor to 80.\n")
+ ;
+ // clang-format on
+
+ _options.add(general);
+ _positional.add("path", -1);
+}
+
+void Args::Parse(const int argc, char **argv)
+{
+ po::variables_map vm;
+ po::store(po::command_line_parser(argc, argv).options(_options).positional(_positional).run(),
+ vm);
+
+ if (vm.count("help"))
+ {
+ std::cout << "onert_train\n\n";
+ std::cout << "Usage: " << argv[0] << "[model path] [<options>]\n\n";
+ std::cout << _options;
+ std::cout << "\n";
+
+ exit(0);
+ }
+
+ if (vm.count("version"))
+ {
+ _print_version = true;
+ return;
+ }
+
+ {
+ auto conflicting_options = [&](const std::string &o1, const std::string &o2) {
+ if ((vm.count(o1) && !vm[o1].defaulted()) && (vm.count(o2) && !vm[o2].defaulted()))
+ {
+ throw boost::program_options::error(std::string("Two options '") + o1 + "' and '" + o2 +
+ "' cannot be given at once.");
+ }
+ };
+
+ // Cannot use both single model file and nnpackage at once
+ conflicting_options("modelfile", "nnpackage");
+
+ // Require modelfile, nnpackage, or path
+ if (!vm.count("modelfile") && !vm.count("nnpackage") && !vm.count("path"))
+ throw boost::program_options::error(
+ std::string("Require one of options modelfile, nnpackage, or path."));
+ }
+
+ try
+ {
+ po::notify(vm);
+ }
+ catch (const std::bad_cast &e)
+ {
+ std::cerr << "Bad cast error - " << e.what() << '\n';
+ exit(1);
+ }
+}
+
+} // end of namespace onert_train
diff --git a/tests/tools/onert_train/src/args.h b/tests/tools/onert_train/src/args.h
new file mode 100644
index 000000000..cbd87e111
--- /dev/null
+++ b/tests/tools/onert_train/src/args.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_TRAIN_ARGS_H__
+#define __ONERT_TRAIN_ARGS_H__
+
+#include <string>
+#include <unordered_map>
+#include <vector>
+#include <boost/program_options.hpp>
+
+#include "types.h"
+
+namespace po = boost::program_options;
+
+namespace onert_train
+{
+
+using TensorShapeMap = std::unordered_map<uint32_t, TensorShape>;
+
+#if defined(ONERT_HAVE_HDF5) && ONERT_HAVE_HDF5 == 1
+enum class WhenToUseH5Shape
+{
+ NOT_PROVIDED, // Param not provided
+ PREPARE, // read shapes in h5 file and set them as inputs' shape before calling nnfw_prepare()
+ RUN, // read shapes in h5 file and set them as inputs' shape before calling nnfw_run()
+};
+#endif
+
+class Args
+{
+public:
+ Args(const int argc, char **argv);
+ void print(void);
+
+ const std::string &getPackageFilename(void) const { return _package_filename; }
+ const std::string &getModelFilename(void) const { return _model_filename; }
+ const bool useSingleModel(void) const { return _use_single_model; }
+ const int getDataLength(void) const { return _data_length; }
+ const std::string &getLoadRawInputFilename(void) const { return _load_raw_input_filename; }
+ const std::string &getLoadRawExpectedFilename(void) const { return _load_raw_expected_filename; }
+ const bool getMemoryPoll(void) const { return _mem_poll; }
+ const int getEpoch(void) const { return _epoch; }
+ const int getBatchSize(void) const { return _batch_size; }
+ const float getLearningRate(void) const { return _learning_rate; }
+ const int getLossType(void) const { return _loss_type; }
+ const int getOptimizerType(void) const { return _optimizer_type; }
+ const bool printVersion(void) const { return _print_version; }
+ const int getVerboseLevel(void) const { return _verbose_level; }
+ std::unordered_map<uint32_t, uint32_t> getOutputSizes(void) const { return _output_sizes; }
+
+private:
+ void Initialize();
+ void Parse(const int argc, char **argv);
+
+private:
+ po::positional_options_description _positional;
+ po::options_description _options;
+
+ std::string _package_filename;
+ std::string _model_filename;
+ bool _use_single_model = false;
+ int _data_length;
+ std::string _load_raw_input_filename;
+ std::string _load_raw_expected_filename;
+ bool _mem_poll;
+ int _epoch;
+ int _batch_size;
+ float _learning_rate;
+ int _loss_type;
+ int _optimizer_type;
+ bool _print_version = false;
+ int _verbose_level;
+ std::unordered_map<uint32_t, uint32_t> _output_sizes;
+};
+
+} // end of namespace onert_train
+
+#endif // __ONERT_TRAIN_ARGS_H__
diff --git a/tests/tools/onert_train/src/formatter.h b/tests/tools/onert_train/src/formatter.h
new file mode 100644
index 000000000..6d256804e
--- /dev/null
+++ b/tests/tools/onert_train/src/formatter.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_TRAIN_FORMATTER_H__
+#define __ONERT_TRAIN_FORMATTER_H__
+
+#include <string>
+#include <vector>
+
+#include "types.h"
+#include "allocation.h"
+
+struct nnfw_session;
+
+namespace onert_train
+{
+class Formatter
+{
+public:
+ virtual ~Formatter() = default;
+ Formatter(nnfw_session *sess) : session_(sess) {}
+ virtual void loadInputs(const std::string &filename, std::vector<Allocation> &inputs) = 0;
+ virtual void dumpOutputs(const std::string &filename, std::vector<Allocation> &outputs) = 0;
+ virtual std::vector<TensorShape> readTensorShapes(const std::string &filename)
+ {
+ return std::vector<TensorShape>();
+ };
+
+protected:
+ nnfw_session *session_;
+};
+} // namespace onert_train
+
+#endif // __ONERT_TRAIN_FORMATTER_H__
diff --git a/tests/tools/onert_train/src/h5formatter.cc b/tests/tools/onert_train/src/h5formatter.cc
new file mode 100644
index 000000000..12c570b5d
--- /dev/null
+++ b/tests/tools/onert_train/src/h5formatter.cc
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "h5formatter.h"
+#include "nnfw.h"
+#include "nnfw_util.h"
+
+#include <iostream>
+#include <stdexcept>
+#include <H5Cpp.h>
+
+namespace
+{
+onert_train::TensorShape getShape(H5::DataSet &data_set)
+{
+ std::vector<hsize_t> h5_shape; // hsize_t is unsigned long long
+ H5::DataSpace data_space = data_set.getSpace();
+ int rank = data_space.getSimpleExtentNdims();
+ h5_shape.resize(rank);
+
+ // read shape info from H5 file
+ data_space.getSimpleExtentDims(h5_shape.data(), NULL);
+
+ onert_train::TensorShape shape;
+ for (auto dim : h5_shape)
+ shape.emplace_back(static_cast<int>(dim));
+
+ return shape;
+}
+} // namespace
+
+namespace onert_train
+{
+static const char *h5_value_grpname = "value";
+
+std::vector<TensorShape> H5Formatter::readTensorShapes(const std::string &filename)
+{
+ uint32_t num_inputs;
+ NNPR_ENSURE_STATUS(nnfw_input_size(session_, &num_inputs));
+ std::vector<TensorShape> tensor_shapes;
+
+ try
+ {
+ H5::Exception::dontPrint();
+
+ H5::H5File file(filename, H5F_ACC_RDONLY);
+ H5::Group value_group = file.openGroup(h5_value_grpname);
+
+ // Constraints: if there are n data set names, they should be unique and
+ // one of [ "0", "1", .. , "n-1" ]
+ for (uint32_t i = 0; i < num_inputs; ++i)
+ {
+ H5::DataSet data_set = value_group.openDataSet(std::to_string(i));
+ H5::DataType type = data_set.getDataType();
+ auto shape = getShape(data_set);
+
+ tensor_shapes.emplace_back(shape);
+ }
+
+ return tensor_shapes;
+ }
+ catch (const H5::Exception &e)
+ {
+ H5::Exception::printErrorStack();
+ std::exit(-1);
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << e.what() << std::endl;
+ std::exit(-1);
+ }
+}
+
+void H5Formatter::loadInputs(const std::string &filename, std::vector<Allocation> &inputs)
+{
+ uint32_t num_inputs;
+ NNPR_ENSURE_STATUS(nnfw_input_size(session_, &num_inputs));
+ try
+ {
+ // Turn off the automatic error printing.
+ H5::Exception::dontPrint();
+
+ H5::H5File file(filename, H5F_ACC_RDONLY);
+ H5::Group value_group = file.openGroup(h5_value_grpname);
+ for (uint32_t i = 0; i < num_inputs; ++i)
+ {
+ nnfw_tensorinfo ti;
+ NNPR_ENSURE_STATUS(nnfw_input_tensorinfo(session_, i, &ti));
+
+ // TODO Add Assert(nnfw shape, h5 file shape size)
+
+ // allocate memory for data
+ auto bufsz = bufsize_for(&ti);
+ inputs[i].alloc(bufsz);
+
+ H5::DataSet data_set = value_group.openDataSet(std::to_string(i));
+ H5::DataType type = data_set.getDataType();
+ switch (ti.dtype)
+ {
+ case NNFW_TYPE_TENSOR_FLOAT32:
+ if (type == H5::PredType::IEEE_F32BE || type == H5::PredType::IEEE_F32LE)
+ data_set.read(inputs[i].data(), H5::PredType::NATIVE_FLOAT);
+ else
+ throw std::runtime_error("model input type is f32. But h5 data type is different.");
+ break;
+ case NNFW_TYPE_TENSOR_INT32:
+ if (type == H5::PredType::STD_I32BE || type == H5::PredType::STD_I32LE)
+ data_set.read(inputs[i].data(), H5::PredType::NATIVE_INT32);
+ else
+ throw std::runtime_error("model input type is i32. But h5 data type is different.");
+ break;
+ case NNFW_TYPE_TENSOR_INT64:
+ if (type == H5::PredType::STD_I64BE || type == H5::PredType::STD_I64LE)
+ data_set.read(inputs[i].data(), H5::PredType::NATIVE_INT64);
+ else
+ throw std::runtime_error("model input type is i64. But h5 data type is different.");
+ break;
+ case NNFW_TYPE_TENSOR_QUANT8_ASYMM:
+ case NNFW_TYPE_TENSOR_BOOL:
+ case NNFW_TYPE_TENSOR_UINT8:
+ if (type == H5::PredType::STD_U8BE || type == H5::PredType::STD_U8LE)
+ data_set.read(inputs[i].data(), H5::PredType::NATIVE_UINT8);
+ else
+ throw std::runtime_error(
+ "model input type is qasymm8, bool or uint8. But h5 data type is different.");
+ break;
+ case NNFW_TYPE_TENSOR_QUANT8_ASYMM_SIGNED:
+ if (type == H5::PredType::STD_I8BE || type == H5::PredType::STD_I8LE)
+ data_set.read(inputs[i].data(), H5::PredType::NATIVE_INT8);
+ else
+ throw std::runtime_error("model input type is int8. But h5 data type is different.");
+ break;
+ case NNFW_TYPE_TENSOR_QUANT16_SYMM_SIGNED:
+ throw std::runtime_error("NYI for NNFW_TYPE_TENSOR_QUANT16_SYMM_SIGNED type");
+ default:
+ throw std::runtime_error("onert_run can load f32, i32, qasymm8, bool and uint8.");
+ }
+ NNPR_ENSURE_STATUS(nnfw_set_input(session_, i, ti.dtype, inputs[i].data(), bufsz));
+ NNPR_ENSURE_STATUS(nnfw_set_input_layout(session_, i, NNFW_LAYOUT_CHANNELS_LAST));
+ }
+ }
+ catch (const H5::Exception &e)
+ {
+ H5::Exception::printErrorStack();
+ std::exit(-1);
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << e.what() << std::endl;
+ std::exit(-1);
+ }
+};
+
+void H5Formatter::dumpOutputs(const std::string &filename, std::vector<Allocation> &outputs)
+{
+ uint32_t num_outputs;
+ NNPR_ENSURE_STATUS(nnfw_output_size(session_, &num_outputs));
+ try
+ {
+ // Turn off the automatic error printing.
+ H5::Exception::dontPrint();
+
+ H5::H5File file(filename, H5F_ACC_TRUNC);
+ H5::Group value_group = file.createGroup(h5_value_grpname);
+ for (uint32_t i = 0; i < num_outputs; i++)
+ {
+ nnfw_tensorinfo ti;
+ NNPR_ENSURE_STATUS(nnfw_output_tensorinfo(session_, i, &ti));
+ std::vector<hsize_t> dims(ti.rank);
+ for (uint32_t j = 0; j < ti.rank; ++j)
+ {
+ if (ti.dims[j] >= 0)
+ dims[j] = static_cast<hsize_t>(ti.dims[j]);
+ else
+ {
+ std::cerr << "Negative dimension in output tensor" << std::endl;
+ exit(-1);
+ }
+ }
+ H5::DataSpace data_space(ti.rank, dims.data());
+ switch (ti.dtype)
+ {
+ case NNFW_TYPE_TENSOR_FLOAT32:
+ {
+ H5::DataSet data_set =
+ value_group.createDataSet(std::to_string(i), H5::PredType::IEEE_F32BE, data_space);
+ data_set.write(outputs[i].data(), H5::PredType::NATIVE_FLOAT);
+ break;
+ }
+ case NNFW_TYPE_TENSOR_INT32:
+ {
+ H5::DataSet data_set =
+ value_group.createDataSet(std::to_string(i), H5::PredType::STD_I32LE, data_space);
+ data_set.write(outputs[i].data(), H5::PredType::NATIVE_INT32);
+ break;
+ }
+ case NNFW_TYPE_TENSOR_INT64:
+ {
+ H5::DataSet data_set =
+ value_group.createDataSet(std::to_string(i), H5::PredType::STD_I64LE, data_space);
+ data_set.write(outputs[i].data(), H5::PredType::NATIVE_INT64);
+ break;
+ }
+ case NNFW_TYPE_TENSOR_UINT8:
+ case NNFW_TYPE_TENSOR_QUANT8_ASYMM:
+ {
+ H5::DataSet data_set =
+ value_group.createDataSet(std::to_string(i), H5::PredType::STD_U8BE, data_space);
+ data_set.write(outputs[i].data(), H5::PredType::NATIVE_UINT8);
+ break;
+ }
+ case NNFW_TYPE_TENSOR_BOOL:
+ {
+ H5::DataSet data_set =
+ value_group.createDataSet(std::to_string(i), H5::PredType::STD_U8LE, data_space);
+ data_set.write(outputs[i].data(), H5::PredType::NATIVE_INT8);
+ break;
+ }
+ case NNFW_TYPE_TENSOR_QUANT8_ASYMM_SIGNED:
+ {
+ H5::DataSet data_set =
+ value_group.createDataSet(std::to_string(i), H5::PredType::STD_I8LE, data_space);
+ data_set.write(outputs[i].data(), H5::PredType::NATIVE_INT8);
+ break;
+ }
+ case NNFW_TYPE_TENSOR_QUANT16_SYMM_SIGNED:
+ throw std::runtime_error("NYI for NNFW_TYPE_TENSOR_QUANT16_SYMM_SIGNED type");
+ default:
+ throw std::runtime_error("onert_run can dump f32, i32, qasymm8, bool and uint8.");
+ }
+ }
+ }
+ catch (const H5::Exception &e)
+ {
+ H5::Exception::printErrorStack();
+ std::exit(-1);
+ }
+ catch (const std::runtime_error &e)
+ {
+ std::cerr << "Error during dumpOutputs on onert_run : " << e.what() << std::endl;
+ std::exit(-1);
+ }
+};
+
+} // end of namespace onert_train
diff --git a/tests/tools/onert_train/src/h5formatter.h b/tests/tools/onert_train/src/h5formatter.h
new file mode 100644
index 000000000..21ef16526
--- /dev/null
+++ b/tests/tools/onert_train/src/h5formatter.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_TRAIN_H5FORMATTER_H__
+#define __ONERT_TRAIN_H5FORMATTER_H__
+
+#include "allocation.h"
+#include "formatter.h"
+#include "types.h"
+
+#include <string>
+#include <vector>
+
+struct nnfw_session;
+
+namespace onert_train
+{
+class H5Formatter : public Formatter
+{
+public:
+ H5Formatter(nnfw_session *sess) : Formatter(sess) {}
+ std::vector<TensorShape> readTensorShapes(const std::string &filename) override;
+ void loadInputs(const std::string &filename, std::vector<Allocation> &inputs) override;
+ void dumpOutputs(const std::string &filename, std::vector<Allocation> &outputs) override;
+};
+} // namespace onert_train
+
+#endif // __ONERT_TRAIN_H5FORMATTER_H__
diff --git a/tests/tools/onert_train/src/measure.h b/tests/tools/onert_train/src/measure.h
new file mode 100644
index 000000000..f7c8610d0
--- /dev/null
+++ b/tests/tools/onert_train/src/measure.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_TRAIN_MEASURE_H__
+#define __ONERT_TRAIN_MEASURE_H__
+
+#include <algorithm>
+#include <ctime>
+#include <vector>
+
+namespace
+{
+uint64_t nowMicros()
+{
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return static_cast<uint64_t>(ts.tv_nsec) / 1e3 + static_cast<uint64_t>(ts.tv_sec) * 1e6;
+}
+} // namespace
+
+namespace onert_train
+{
+
+struct Step
+{
+ uint64_t time; // us
+ // TODO Support memory usage
+};
+
+class Measure
+{
+public:
+ Measure() = default;
+
+ void set(const int epoch, const int step)
+ {
+ _results.clear();
+ _results.resize(epoch);
+ std::for_each(_results.begin(), _results.end(), [step](auto &v) { v.resize(step); });
+ }
+
+ void run(const int epoch, const int step, const std::function<void()> &func)
+ {
+ if (_results.empty() || _results.size() <= epoch || _results[epoch].size() <= step)
+ {
+ throw std::runtime_error("Please set the number of epochs and steps first");
+ }
+
+ _results[epoch][step].time = nowMicros();
+
+ func();
+
+ _results[epoch][step].time = nowMicros() - _results[epoch][step].time;
+ }
+
+ double timeMicros(const int epoch)
+ {
+ if (_results.empty() || _results.size() <= epoch)
+ {
+ throw std::runtime_error("Invalid epoch");
+ }
+
+ double sum = 0u;
+ std::for_each(_results[epoch].begin(), _results[epoch].end(),
+ [&sum](auto &v) { sum += v.time; });
+ return sum / _results[epoch].size();
+ }
+
+ double timeMs(const int epoch) { return timeMicros(epoch) / 1e3; }
+
+private:
+ std::vector<std::vector<Step>> _results;
+};
+
+} // namespace onert_train
+
+#endif // __ONERT_TRAIN_MEASURE_H__
diff --git a/tests/tools/onert_train/src/nnfw_util.cc b/tests/tools/onert_train/src/nnfw_util.cc
new file mode 100644
index 000000000..8dd2aa871
--- /dev/null
+++ b/tests/tools/onert_train/src/nnfw_util.cc
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cassert>
+#include <string>
+#include "nnfw.h"
+
+namespace onert_train
+{
+uint64_t num_elems(const nnfw_tensorinfo *ti)
+{
+ uint64_t n = 1;
+ for (uint32_t i = 0; i < ti->rank; ++i)
+ {
+ assert(ti->dims[i] >= 0);
+ n *= ti->dims[i];
+ }
+ return n;
+}
+
+uint64_t bufsize_for(const nnfw_tensorinfo *ti)
+{
+ static int elmsize[] = {
+ sizeof(float), /* NNFW_TYPE_TENSOR_FLOAT32 */
+ sizeof(int), /* NNFW_TYPE_TENSOR_INT32 */
+ sizeof(uint8_t), /* NNFW_TYPE_TENSOR_QUANT8_ASYMM */
+ sizeof(bool), /* NNFW_TYPE_TENSOR_BOOL = 3 */
+ sizeof(uint8_t), /* NNFW_TYPE_TENSOR_UINT8 = 4 */
+ sizeof(int64_t), /* NNFW_TYPE_TENSOR_INT64 = 5 */
+ sizeof(int8_t), /* NNFW_TYPE_TENSOR_QUANT8_ASYMM_SIGNED = 6 */
+ sizeof(int16_t), /* NNFW_TYPE_TENSOR_QUANT16_SYMM_SIGNED = 7 */
+ };
+ return elmsize[ti->dtype] * num_elems(ti);
+}
+
+} // namespace onert_train
diff --git a/tests/tools/onert_train/src/nnfw_util.h b/tests/tools/onert_train/src/nnfw_util.h
new file mode 100644
index 000000000..674e18fb2
--- /dev/null
+++ b/tests/tools/onert_train/src/nnfw_util.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_TRAIN_NNFW_UTIL_H__
+#define __ONERT_TRAIN_NNFW_UTIL_H__
+
+#include "nnfw.h"
+
+#define NNPR_ENSURE_STATUS(a) \
+ do \
+ { \
+ if ((a) != NNFW_STATUS_NO_ERROR) \
+ { \
+ exit(-1); \
+ } \
+ } while (0)
+
+namespace onert_train
+{
+uint64_t num_elems(const nnfw_tensorinfo *ti);
+uint64_t bufsize_for(const nnfw_tensorinfo *ti);
+} // end of namespace onert_train
+
+#endif // __ONERT_TRAIN_NNFW_UTIL_H__
diff --git a/tests/tools/onert_train/src/onert_train.cc b/tests/tools/onert_train/src/onert_train.cc
new file mode 100644
index 000000000..678d13fc9
--- /dev/null
+++ b/tests/tools/onert_train/src/onert_train.cc
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "allocation.h"
+#include "args.h"
+#include "benchmark.h"
+#include "measure.h"
+#include "nnfw.h"
+#include "nnfw_util.h"
+#include "nnfw_internal.h"
+#include "nnfw_experimental.h"
+#include "randomgen.h"
+#include "rawformatter.h"
+#include "rawdataloader.h"
+
+#include <boost/program_options.hpp>
+#include <cassert>
+#include <chrono>
+#include <cstdlib>
+#include <iostream>
+#include <libgen.h>
+#include <stdexcept>
+#include <unordered_map>
+#include <vector>
+
+static const char *default_backend_cand = "train";
+
+int main(const int argc, char **argv)
+{
+ using namespace onert_train;
+
+ try
+ {
+ Args args(argc, argv);
+ if (args.printVersion())
+ {
+ uint32_t version;
+ NNPR_ENSURE_STATUS(nnfw_query_info_u32(NULL, NNFW_INFO_ID_VERSION, &version));
+ std::cout << "onert_train (nnfw runtime: v" << (version >> 24) << "."
+ << ((version & 0x0000FF00) >> 8) << "." << (version & 0xFF) << ")" << std::endl;
+ exit(0);
+ }
+
+ // TODO Apply verbose level to phases
+ const int verbose = args.getVerboseLevel();
+ benchmark::Phases phases(benchmark::PhaseOption{});
+
+ nnfw_session *session = nullptr;
+ NNPR_ENSURE_STATUS(nnfw_create_session(&session));
+
+ // ModelLoad
+ phases.run("MODEL_LOAD", [&](const benchmark::Phase &, uint32_t) {
+ if (args.useSingleModel())
+ NNPR_ENSURE_STATUS(
+ nnfw_load_model_from_modelfile(session, args.getModelFilename().c_str()));
+ else
+ NNPR_ENSURE_STATUS(nnfw_load_model_from_file(session, args.getPackageFilename().c_str()));
+ });
+
+ // Set training backend
+ NNPR_ENSURE_STATUS(nnfw_set_available_backends(session, default_backend_cand));
+
+ uint32_t num_inputs;
+ NNPR_ENSURE_STATUS(nnfw_input_size(session, &num_inputs));
+
+ uint32_t num_expecteds;
+ NNPR_ENSURE_STATUS(nnfw_output_size(session, &num_expecteds));
+
+ // verify input and output
+
+ auto verifyInputTypes = [session]() {
+ uint32_t sz;
+ NNPR_ENSURE_STATUS(nnfw_input_size(session, &sz));
+ for (uint32_t i = 0; i < sz; ++i)
+ {
+ nnfw_tensorinfo ti;
+ NNPR_ENSURE_STATUS(nnfw_input_tensorinfo(session, i, &ti));
+
+ if (ti.dtype < NNFW_TYPE_TENSOR_FLOAT32 || ti.dtype > NNFW_TYPE_TENSOR_QUANT16_SYMM_SIGNED)
+ {
+ std::cerr << "E: not supported input type" << std::endl;
+ exit(-1);
+ }
+ }
+ };
+
+ auto verifyOutputTypes = [session]() {
+ uint32_t sz;
+ NNPR_ENSURE_STATUS(nnfw_output_size(session, &sz));
+
+ for (uint32_t i = 0; i < sz; ++i)
+ {
+ nnfw_tensorinfo ti;
+ NNPR_ENSURE_STATUS(nnfw_output_tensorinfo(session, i, &ti));
+
+ if (ti.dtype < NNFW_TYPE_TENSOR_FLOAT32 || ti.dtype > NNFW_TYPE_TENSOR_QUANT16_SYMM_SIGNED)
+ {
+ std::cerr << "E: not supported output type" << std::endl;
+ exit(-1);
+ }
+ }
+ };
+
+ verifyInputTypes();
+ verifyOutputTypes();
+
+ auto convertLossType = [](int type) {
+ switch (type)
+ {
+ case 0:
+ return NNFW_TRAIN_LOSS_MEAN_SQUARED_ERROR;
+ case 1:
+ return NNFW_TRAIN_LOSS_CATEGORICAL_CROSSENTROPY;
+ default:
+ std::cerr << "E: not supported loss type" << std::endl;
+ exit(-1);
+ }
+ };
+
+ auto convertOptType = [](int type) {
+ switch (type)
+ {
+ case 0:
+ return NNFW_TRAIN_OPTIMIZER_SGD;
+ case 1:
+ return NNFW_TRAIN_OPTIMIZER_ADAM;
+ default:
+ std::cerr << "E: not supported optimizer type" << std::endl;
+ exit(-1);
+ }
+ };
+
+ // prepare training info
+ nnfw_train_info tri;
+ tri.batch_size = args.getBatchSize();
+ tri.learning_rate = args.getLearningRate();
+ tri.loss = convertLossType(args.getLossType());
+ tri.opt = convertOptType(args.getOptimizerType());
+
+ // prepare execution
+
+ // TODO When nnfw_{prepare|run} are failed, can't catch the time
+ phases.run("PREPARE", [&](const benchmark::Phase &, uint32_t) {
+ NNPR_ENSURE_STATUS(nnfw_train_prepare(session, &tri));
+ });
+
+ // prepare input and expected tensor info lists
+ std::vector<nnfw_tensorinfo> input_infos;
+ std::vector<nnfw_tensorinfo> expected_infos;
+
+ // prepare data buffers
+ std::vector<Allocation> input_data(num_inputs);
+ std::vector<Allocation> expected_data(num_expecteds);
+
+ for (uint32_t i = 0; i < num_inputs; ++i)
+ {
+ nnfw_tensorinfo ti;
+ NNPR_ENSURE_STATUS(nnfw_input_tensorinfo(session, i, &ti));
+ input_data[i].alloc(bufsize_for(&ti));
+ input_infos.emplace_back(std::move(ti));
+ }
+
+ for (uint32_t i = 0; i < num_expecteds; ++i)
+ {
+ nnfw_tensorinfo ti;
+ NNPR_ENSURE_STATUS(nnfw_output_tensorinfo(session, i, &ti));
+ expected_data[i].alloc(bufsize_for(&ti));
+ expected_infos.emplace_back(std::move(ti));
+ }
+
+ auto data_length = args.getDataLength();
+
+ Generator generator;
+ RawDataLoader rawDataLoader;
+
+ if (!args.getLoadRawInputFilename().empty() && !args.getLoadRawExpectedFilename().empty())
+ {
+ generator =
+ rawDataLoader.loadData(args.getLoadRawInputFilename(), args.getLoadRawExpectedFilename(),
+ input_infos, expected_infos, data_length, tri.batch_size);
+ }
+ else
+ {
+ // TODO Use random generator
+ std::cerr << "E: not supported random input and expected generator" << std::endl;
+ exit(-1);
+ }
+
+ Measure measure;
+ std::vector<float> losses(num_expecteds);
+ phases.run("EXECUTE", [&](const benchmark::Phase &, uint32_t) {
+ const int num_step = data_length / tri.batch_size;
+ const int num_epoch = args.getEpoch();
+ measure.set(num_epoch, num_step);
+ for (uint32_t epoch = 0; epoch < num_epoch; ++epoch)
+ {
+ std::fill(losses.begin(), losses.end(), 0);
+ for (uint32_t n = 0; n < num_step; ++n)
+ {
+ // get batchsize data
+ if (!generator(n, input_data, expected_data))
+ break;
+
+ // prepare input
+ for (uint32_t i = 0; i < num_inputs; ++i)
+ {
+ NNPR_ENSURE_STATUS(
+ nnfw_train_set_input(session, i, input_data[i].data(), &input_infos[i]));
+ }
+
+ // prepare output
+ for (uint32_t i = 0; i < num_expecteds; ++i)
+ {
+ NNPR_ENSURE_STATUS(
+ nnfw_train_set_expected(session, i, expected_data[i].data(), &expected_infos[i]));
+ }
+
+ // train
+ measure.run(epoch, n, [&]() { NNPR_ENSURE_STATUS(nnfw_train(session, true)); });
+
+ // store loss
+ for (int32_t i = 0; i < num_expecteds; ++i)
+ {
+ float temp = 0.f;
+ NNPR_ENSURE_STATUS(nnfw_train_get_loss(session, i, &temp));
+ losses[i] += temp;
+ }
+ }
+
+ // print loss
+ std::cout << std::fixed;
+ std::cout.precision(3);
+ std::cout << "Epoch " << epoch + 1 << "/" << num_epoch << " - " << measure.timeMs(epoch)
+ << "ms/step - loss: ";
+ std::cout.precision(4);
+ for (uint32_t i = 0; i < num_expecteds; ++i)
+ {
+ std::cout << "[" << i << "] " << losses[i] / num_step;
+ }
+ std::cout /* << "- accuracy: " << accuracy*/ << std::endl;
+ }
+ });
+
+ NNPR_ENSURE_STATUS(nnfw_close_session(session));
+
+ // prepare result
+ benchmark::Result result(phases);
+
+ // to stdout
+ benchmark::printResult(result);
+
+ return 0;
+ }
+ catch (boost::program_options::error &e)
+ {
+ std::cerr << "E: " << e.what() << std::endl;
+ exit(-1);
+ }
+ catch (std::runtime_error &e)
+ {
+ std::cerr << "E: Fail to run by runtime error:" << e.what() << std::endl;
+ exit(-1);
+ }
+}
diff --git a/tests/tools/onert_train/src/randomgen.cc b/tests/tools/onert_train/src/randomgen.cc
new file mode 100644
index 000000000..72599cbb2
--- /dev/null
+++ b/tests/tools/onert_train/src/randomgen.cc
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "randomgen.h"
+#include "nnfw.h"
+#include "nnfw_util.h"
+#include "misc/RandomGenerator.h"
+
+#include <iostream>
+
+namespace onert_train
+{
+
+template <class T> void randomData(nnfw::misc::RandomGenerator &randgen, void *data, uint64_t size)
+{
+ for (uint64_t i = 0; i < size; i++)
+ reinterpret_cast<T *>(data)[i] = randgen.generate<T>();
+}
+
+void RandomGenerator::generate(std::vector<Allocation> &inputs)
+{
+ // generate random data
+ const int seed = 1;
+ nnfw::misc::RandomGenerator randgen{seed, 0.0f, 2.0f};
+ for (uint32_t i = 0; i < inputs.size(); ++i)
+ {
+ nnfw_tensorinfo ti;
+ NNPR_ENSURE_STATUS(nnfw_input_tensorinfo(session_, i, &ti));
+ auto input_size_in_bytes = bufsize_for(&ti);
+ inputs[i].alloc(input_size_in_bytes);
+ switch (ti.dtype)
+ {
+ case NNFW_TYPE_TENSOR_FLOAT32:
+ randomData<float>(randgen, inputs[i].data(), num_elems(&ti));
+ break;
+ case NNFW_TYPE_TENSOR_QUANT8_ASYMM:
+ randomData<uint8_t>(randgen, inputs[i].data(), num_elems(&ti));
+ break;
+ case NNFW_TYPE_TENSOR_BOOL:
+ randomData<bool>(randgen, inputs[i].data(), num_elems(&ti));
+ break;
+ case NNFW_TYPE_TENSOR_UINT8:
+ randomData<uint8_t>(randgen, inputs[i].data(), num_elems(&ti));
+ break;
+ case NNFW_TYPE_TENSOR_INT32:
+ randomData<int32_t>(randgen, inputs[i].data(), num_elems(&ti));
+ break;
+ case NNFW_TYPE_TENSOR_INT64:
+ randomData<int64_t>(randgen, inputs[i].data(), num_elems(&ti));
+ break;
+ case NNFW_TYPE_TENSOR_QUANT16_SYMM_SIGNED:
+ randomData<int16_t>(randgen, inputs[i].data(), num_elems(&ti));
+ break;
+ default:
+ std::cerr << "Not supported input type" << std::endl;
+ std::exit(-1);
+ }
+ NNPR_ENSURE_STATUS(
+ nnfw_set_input(session_, i, ti.dtype, inputs[i].data(), input_size_in_bytes));
+ NNPR_ENSURE_STATUS(nnfw_set_input_layout(session_, i, NNFW_LAYOUT_CHANNELS_LAST));
+ }
+};
+
+} // end of namespace onert_train
diff --git a/tests/tools/onert_train/src/randomgen.h b/tests/tools/onert_train/src/randomgen.h
new file mode 100644
index 000000000..410c66d6f
--- /dev/null
+++ b/tests/tools/onert_train/src/randomgen.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_TRAIN_RANDOMGEN_H__
+#define __ONERT_TRAIN_RANDOMGEN_H__
+
+#include <string>
+#include <vector>
+
+#include "allocation.h"
+
+struct nnfw_session;
+
+namespace onert_train
+{
+class RandomGenerator
+{
+public:
+ RandomGenerator(nnfw_session *sess) : session_(sess) {}
+ void generate(std::vector<Allocation> &inputs);
+
+private:
+ nnfw_session *session_;
+};
+} // namespace onert_train
+
+#endif // __ONERT_TRAIN_RANDOMGEN_H__
diff --git a/tests/tools/onert_train/src/rawdataloader.cc b/tests/tools/onert_train/src/rawdataloader.cc
new file mode 100644
index 000000000..a3672a9f3
--- /dev/null
+++ b/tests/tools/onert_train/src/rawdataloader.cc
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rawdataloader.h"
+#include "nnfw_util.h"
+
+#include <iostream>
+#include <stdexcept>
+#include <numeric>
+
+namespace onert_train
+{
+
+Generator RawDataLoader::loadData(const std::string &input_file, const std::string &expected_file,
+ const std::vector<nnfw_tensorinfo> &input_infos,
+ const std::vector<nnfw_tensorinfo> &expected_infos,
+ const uint32_t data_length, const uint32_t batch_size)
+{
+ std::vector<uint32_t> input_origins(input_infos.size());
+ uint32_t start = 0;
+ for (uint32_t i = 0; i < input_infos.size(); ++i)
+ {
+ input_origins.at(i) = start;
+ start += (bufsize_for(&input_infos[i]) / batch_size * data_length);
+ }
+
+ std::vector<uint32_t> expected_origins(expected_infos.size());
+ start = 0;
+ for (uint32_t i = 0; i < expected_infos.size(); ++i)
+ {
+ expected_origins.at(i) = start;
+ start += (bufsize_for(&expected_infos[i]) / batch_size * data_length);
+ }
+
+ try
+ {
+ _input_file = std::ifstream(input_file, std::ios::ate | std::ios::binary);
+ _expected_file = std::ifstream(expected_file, std::ios::ate | std::ios::binary);
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << e.what() << std::endl;
+ std::exit(-1);
+ }
+
+ return [input_origins, expected_origins, &input_infos, &expected_infos,
+ this](uint32_t idx, std::vector<Allocation> &inputs, std::vector<Allocation> &expecteds) {
+ for (uint32_t i = 0; i < input_infos.size(); ++i)
+ {
+ auto bufsz = bufsize_for(&input_infos[i]);
+ _input_file.seekg(input_origins[i] + idx * bufsz, std::ios::beg);
+ _input_file.read(reinterpret_cast<char *>(inputs[i].data()), bufsz);
+ }
+ for (uint32_t i = 0; i < expected_infos.size(); ++i)
+ {
+ auto bufsz = bufsize_for(&expected_infos[i]);
+ _expected_file.seekg(expected_origins[i] + idx * bufsz, std::ios::beg);
+ _expected_file.read(reinterpret_cast<char *>(expecteds[i].data()), bufsz);
+ }
+ return true;
+ };
+}
+
+} // namespace onert_train
diff --git a/tests/tools/onert_train/src/rawdataloader.h b/tests/tools/onert_train/src/rawdataloader.h
new file mode 100644
index 000000000..3fb292770
--- /dev/null
+++ b/tests/tools/onert_train/src/rawdataloader.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_TRAIN_RAWDATALOADER_H__
+#define __ONERT_TRAIN_RAWDATALOADER_H__
+
+#include "allocation.h"
+#include "nnfw.h"
+
+#include <functional>
+#include <string>
+#include <vector>
+#include <fstream>
+
+namespace onert_train
+{
+
+using Generator = std::function<bool(uint32_t, /** index **/
+ std::vector<Allocation> &, /** input **/
+ std::vector<Allocation> & /** expected **/)>;
+
+class RawDataLoader
+{
+public:
+ RawDataLoader() = default;
+ Generator loadData(const std::string &input_file, const std::string &expected_file,
+ const std::vector<nnfw_tensorinfo> &input_infos,
+ const std::vector<nnfw_tensorinfo> &output_infos, const uint32_t data_length,
+ const uint32_t batch_size);
+
+private:
+ std::ifstream _input_file;
+ std::ifstream _expected_file;
+};
+
+} // namespace onert_train
+
+#endif // __ONERT_TRAIN_RAWDATALOADER_H__
diff --git a/tests/tools/onert_train/src/rawformatter.cc b/tests/tools/onert_train/src/rawformatter.cc
new file mode 100644
index 000000000..a17071684
--- /dev/null
+++ b/tests/tools/onert_train/src/rawformatter.cc
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rawformatter.h"
+#include "nnfw.h"
+#include "nnfw_util.h"
+
+#include <iostream>
+#include <fstream>
+#include <stdexcept>
+
+namespace onert_train
+{
+void RawFormatter::loadInputs(const std::string &filename, std::vector<Allocation> &inputs)
+{
+ uint32_t num_inputs;
+ NNPR_ENSURE_STATUS(nnfw_input_size(session_, &num_inputs));
+
+ // Support multiple inputs
+ // Option 1: Get comman-separated input file list like --load:raw a,b,c
+ // Option 2: Get prefix --load:raw in
+ // Internally access in.0, in.1, in.2, ... in.{N-1} where N is determined by nnfw info
+ // query api.
+ //
+ // Currently Option 2 is implemented.
+ try
+ {
+ for (uint32_t i = 0; i < num_inputs; ++i)
+ {
+ nnfw_tensorinfo ti;
+ NNPR_ENSURE_STATUS(nnfw_input_tensorinfo(session_, i, &ti));
+
+ // allocate memory for data
+ auto bufsz = bufsize_for(&ti);
+ inputs[i].alloc(bufsz);
+
+ std::ifstream file(filename + "." + std::to_string(i), std::ios::ate | std::ios::binary);
+ auto filesz = file.tellg();
+ if (bufsz != filesz)
+ {
+ throw std::runtime_error("Input " + std::to_string(i) +
+ " size does not match: " + std::to_string(bufsz) +
+ " expected, but " + std::to_string(filesz) + " provided.");
+ }
+ file.seekg(0, std::ios::beg);
+ file.read(reinterpret_cast<char *>(inputs[i].data()), filesz);
+ file.close();
+
+ NNPR_ENSURE_STATUS(nnfw_set_input(session_, i, ti.dtype, inputs[i].data(), bufsz));
+ NNPR_ENSURE_STATUS(nnfw_set_input_layout(session_, i, NNFW_LAYOUT_CHANNELS_LAST));
+ }
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << e.what() << std::endl;
+ std::exit(-1);
+ }
+};
+
+void RawFormatter::dumpOutputs(const std::string &filename, std::vector<Allocation> &outputs)
+{
+ uint32_t num_outputs;
+ NNPR_ENSURE_STATUS(nnfw_output_size(session_, &num_outputs));
+ try
+ {
+ for (uint32_t i = 0; i < num_outputs; i++)
+ {
+ nnfw_tensorinfo ti;
+ NNPR_ENSURE_STATUS(nnfw_output_tensorinfo(session_, i, &ti));
+ auto bufsz = bufsize_for(&ti);
+
+ std::ofstream file(filename + "." + std::to_string(i), std::ios::out | std::ios::binary);
+ file.write(reinterpret_cast<const char *>(outputs[i].data()), bufsz);
+ file.close();
+ std::cerr << filename + "." + std::to_string(i) + " is generated.\n";
+ }
+ }
+ catch (const std::runtime_error &e)
+ {
+ std::cerr << "Error during dumpOutputs on onert_run : " << e.what() << std::endl;
+ std::exit(-1);
+ }
+}
+} // end of namespace onert_train
diff --git a/tests/tools/onert_train/src/rawformatter.h b/tests/tools/onert_train/src/rawformatter.h
new file mode 100644
index 000000000..90e81b2e9
--- /dev/null
+++ b/tests/tools/onert_train/src/rawformatter.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ONERT_TRAIN_RAWFORMATTER_H__
+#define __ONERT_TRAIN_RAWFORMATTER_H__
+
+#include "allocation.h"
+#include "formatter.h"
+#include "types.h"
+
+#include <string>
+#include <vector>
+
+struct nnfw_session;
+
+namespace onert_train
+{
+class RawFormatter : public Formatter
+{
+public:
+ RawFormatter(nnfw_session *sess) : Formatter(sess) {}
+ void loadInputs(const std::string &filename, std::vector<Allocation> &inputs) override;
+ void dumpOutputs(const std::string &filename, std::vector<Allocation> &outputs) override;
+};
+} // namespace onert_train
+
+#endif // __ONERT_TRAIN_RAWFORMATTER_H__
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALFill.h b/tests/tools/onert_train/src/types.h
index c9eb33b4d..6e2693016 100644
--- a/onert-micro/luci-interpreter/pal/mcu/PALFill.h
+++ b/tests/tools/onert_train/src/types.h
@@ -1,6 +1,5 @@
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,9 +14,14 @@
* limitations under the License.
*/
-#ifndef LUCI_INTERPRETER_PAL_FILL_H
-#define LUCI_INTERPRETER_PAL_FILL_H
+#ifndef __ONERT_TRAIN_TYPES_H__
+#define __ONERT_TRAIN_TYPES_H__
-#include "PALreference_ops.h"
+namespace onert_train
+{
-#endif // LUCI_INTERPRETER_PAL_FILL_H
+using TensorShape = std::vector<int>;
+
+} // end of namespace onert_train
+
+#endif // __ONERT_TRAIN_TYPES_H__
diff --git a/tests/tools/onert_train/test/rawdataloader.test.cc b/tests/tools/onert_train/test/rawdataloader.test.cc
new file mode 100644
index 000000000..b2930b37e
--- /dev/null
+++ b/tests/tools/onert_train/test/rawdataloader.test.cc
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <nnfw.h>
+
+#include <gtest/gtest.h>
+#include <algorithm>
+#include <numeric>
+
+#include "../src/rawdataloader.h"
+#include "../src/nnfw_util.h"
+
+namespace
+{
+using namespace onert_train;
+
+class DataFileGenerator
+{
+public:
+ DataFileGenerator(uint32_t data_length)
+ : _data_length{data_length}, _input_file{"input.bin"}, _expected_file{"expected.bin"}
+ {
+ }
+ ~DataFileGenerator()
+ {
+ try
+ {
+ if (std::remove(_input_file.c_str()) != 0)
+ {
+ std::cerr << "Failed to remove " << _input_file << std::endl;
+ }
+ if (std::remove(_expected_file.c_str()) != 0)
+ {
+ std::cerr << "Failed to remove " << _expected_file << std::endl;
+ }
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Exception: " << e.what() << std::endl;
+ }
+ }
+
+ template <typename T>
+ const std::string &generateInputData(const std::vector<std::vector<T>> &data)
+ {
+ generateData(_input_file, data);
+ return _input_file;
+ }
+
+ template <typename T>
+ const std::string &generateExpectedData(const std::vector<std::vector<T>> &data)
+ {
+ generateData(_expected_file, data);
+ return _expected_file;
+ }
+
+private:
+ template <typename T>
+ void generateData(const std::string &name, const std::vector<std::vector<T>> &data)
+ {
+ try
+ {
+ std::ofstream file(name, std::ios::binary);
+ for (uint32_t i = 0; i < data.size(); ++i)
+ {
+ for (uint32_t j = 0; j < _data_length; ++j)
+ {
+ for (uint32_t k = 0; k < data[i].size(); ++k)
+ {
+ file.write(reinterpret_cast<const char *>(&data[i][k]), sizeof(data[i][k]));
+ }
+ }
+ }
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Exception: " << e.what() << std::endl;
+ }
+ }
+
+private:
+ uint32_t _data_length;
+ std::string _input_file;
+ std::string _expected_file;
+};
+
+class RawDataLoaderTest : public testing::Test
+{
+protected:
+ void SetUp() override { nnfw_create_session(&_session); }
+
+ void TearDown() override { nnfw_close_session(_session); }
+
+ nnfw_session *_session = nullptr;
+};
+
+TEST_F(RawDataLoaderTest, loadDatas_1)
+{
+ const uint32_t data_length = 100;
+ const uint32_t num_input = 1;
+ const uint32_t num_expected = 1;
+ const uint32_t batch_size = 16;
+
+ // Set data tensor info
+ nnfw_tensorinfo in_info = {
+ .dtype = NNFW_TYPE_TENSOR_INT32,
+ .rank = 4,
+ .dims = {batch_size, 2, 2, 2},
+ };
+ std::vector<nnfw_tensorinfo> in_infos{in_info};
+
+ nnfw_tensorinfo expected_info = {
+ .dtype = NNFW_TYPE_TENSOR_INT32,
+ .rank = 4,
+ .dims = {batch_size, 1, 1, 1},
+ };
+ std::vector<nnfw_tensorinfo> expected_infos{expected_info};
+
+ // Generate test data
+ std::vector<std::vector<uint32_t>> in(num_input);
+ for (uint32_t i = 0; i < num_input; ++i)
+ {
+ in[i].resize(num_elems(&in_infos[i]) / batch_size);
+ std::generate(in[i].begin(), in[i].end(), [this] {
+ static uint32_t i = 0;
+ return i++;
+ });
+ }
+
+ std::vector<std::vector<uint32_t>> expected(num_expected);
+ for (uint32_t i = 0; i < num_expected; ++i)
+ {
+ expected[i].resize(num_elems(&expected_infos[i]) / batch_size);
+ std::generate(expected[i].begin(), expected[i].end(), [in, i] {
+ auto sum = std::accumulate(in[i].begin(), in[i].end(), 0);
+ return sum;
+ });
+ }
+
+ // Generate test data file
+ DataFileGenerator file_gen(data_length);
+ auto &input_file = file_gen.generateInputData<uint32_t>(in);
+ auto &expected_file = file_gen.generateExpectedData<uint32_t>(expected);
+
+ // Set expected datas
+ std::vector<std::vector<uint32_t>> expected_in(num_input);
+ std::vector<std::vector<uint32_t>> expected_ex(num_expected);
+ for (uint32_t i = 0; i < num_input; ++i)
+ {
+ for (uint32_t j = 0; j < batch_size; ++j)
+ {
+ expected_in[i].insert(expected_in[i].end(), in[i].begin(), in[i].end());
+ }
+ }
+ for (uint32_t i = 0; i < num_expected; ++i)
+ {
+ for (uint32_t j = 0; j < batch_size; ++j)
+ {
+ expected_ex[i].insert(expected_ex[i].end(), expected[i].begin(), expected[i].end());
+ }
+ }
+
+ // Load test datas
+ RawDataLoader loader;
+ Generator generator =
+ loader.loadData(input_file, expected_file, in_infos, expected_infos, data_length, batch_size);
+
+ // Allocate inputs and expecteds data memory
+ std::vector<Allocation> inputs(num_input);
+ for (uint32_t i = 0; i < num_input; ++i)
+ {
+ inputs[i].alloc(bufsize_for(&in_infos[i]));
+ }
+ std::vector<Allocation> expecteds(num_expected);
+ for (uint32_t i = 0; i < num_expected; ++i)
+ {
+ expecteds[i].alloc(bufsize_for(&expected_infos[i]));
+ }
+
+ uint32_t num_sample = data_length / batch_size;
+ for (uint32_t i = 0; i < num_sample; ++i)
+ {
+ auto data = generator(i, inputs, expecteds);
+
+ std::vector<std::vector<uint32_t>> gen_in(num_input);
+ for (uint32_t h = 0; h < num_input; ++h)
+ {
+ auto num_elem = num_elems(&in_infos[h]);
+ for (uint32_t k = 0; k < num_elem; ++k)
+ {
+ auto inbufs = reinterpret_cast<uint32_t *>(inputs[h].data()) + k;
+ gen_in[h].emplace_back(*inbufs);
+ }
+ }
+ std::vector<std::vector<uint32_t>> gen_ex(num_expected);
+ for (uint32_t h = 0; h < num_expected; ++h)
+ {
+ auto num_elem = num_elems(&expected_infos[h]);
+ for (uint32_t k = 0; k < num_elem; ++k)
+ {
+ auto exbufs = reinterpret_cast<uint32_t *>(expecteds[h].data()) + k;
+ gen_ex[h].emplace_back(*exbufs);
+ }
+ }
+
+ EXPECT_EQ(gen_in, expected_in);
+ EXPECT_EQ(gen_ex, expected_ex);
+ }
+}
+
+} // namespace
diff --git a/tools/cross/aarch64/sources.list.jammy b/tools/cross/aarch64/sources.list.jammy
new file mode 100644
index 000000000..6bb045302
--- /dev/null
+++ b/tools/cross/aarch64/sources.list.jammy
@@ -0,0 +1,11 @@
+deb http://ports.ubuntu.com/ubuntu-ports/ jammy main restricted universe
+deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy main restricted universe
+
+deb http://ports.ubuntu.com/ubuntu-ports/ jammy-updates main restricted universe
+deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy-updates main restricted universe
+
+deb http://ports.ubuntu.com/ubuntu-ports/ jammy-backports main restricted
+deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy-backports main restricted
+
+deb http://ports.ubuntu.com/ubuntu-ports/ jammy-security main restricted universe multiverse
+deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy-security main restricted universe multiverse
diff --git a/tools/cross/aarch64/sources.list.xenial b/tools/cross/aarch64/sources.list.xenial
deleted file mode 100644
index 56fbb36a5..000000000
--- a/tools/cross/aarch64/sources.list.xenial
+++ /dev/null
@@ -1,11 +0,0 @@
-deb http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted universe
-deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted universe
-
-deb http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted universe
-deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted universe
-
-deb http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted
-deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted
-
-deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse
-deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse
diff --git a/tools/cross/armel/tizen-build-rootfs.sh b/tools/cross/armel/tizen-build-rootfs.sh
deleted file mode 100755
index 2d0084d03..000000000
--- a/tools/cross/armel/tizen-build-rootfs.sh
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env bash
-set -e
-
-__ARM_SOFTFP_CrossDir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
-
-if [[ -z "$ROOTFS_DIR" ]]; then
- echo "ROOTFS_DIR is not defined."
- exit 1;
-fi
-
-# Clean-up (TODO-Cleanup: We may already delete $ROOTFS_DIR at ./cross/build-rootfs.sh.)
-# hk0110
-if [ -d "$ROOTFS_DIR" ]; then
- umount $ROOTFS_DIR/*
- rm -rf $ROOTFS_DIR
-fi
-
-TIZEN_TMP_DIR=$ROOTFS_DIR/tizen_tmp
-mkdir -p $TIZEN_TMP_DIR
-
-# Download files
-echo ">>Start downloading files"
-VERBOSE=1 $__ARM_SOFTFP_CrossDir/tizen-fetch.sh $TIZEN_TMP_DIR
-echo "<<Finish downloading files"
-
-echo ">>Start constructing Tizen rootfs"
-TIZEN_RPM_FILES=`ls $TIZEN_TMP_DIR/*.rpm`
-cd $ROOTFS_DIR
-for f in $TIZEN_RPM_FILES; do
- rpm2cpio $f | cpio -idm --quiet
-done
-echo "<<Finish constructing Tizen rootfs"
-
-# Cleanup tmp
-rm -rf $TIZEN_TMP_DIR
-
-# Configure Tizen rootfs
-echo ">>Start configuring Tizen rootfs"
-rm ./usr/lib/libunwind.so
-ln -s libunwind.so.8 ./usr/lib/libunwind.so
-ln -sfn asm-arm ./usr/include/asm
-patch -p1 < $__ARM_SOFTFP_CrossDir/tizen.patch
-echo "<<Finish configuring Tizen rootfs"
diff --git a/tools/cross/armel/tizen-fetch.sh b/tools/cross/armel/tizen-fetch.sh
deleted file mode 100755
index 51fbe81b3..000000000
--- a/tools/cross/armel/tizen-fetch.sh
+++ /dev/null
@@ -1,169 +0,0 @@
-#!/usr/bin/env bash
-set -e
-
-if [[ -z "${VERBOSE// }" ]] || [ "$VERBOSE" -ne "$VERBOSE" ] 2>/dev/null; then
- VERBOSE=0
-fi
-
-Log()
-{
- if [ $VERBOSE -ge $1 ]; then
- echo ${@:2}
- fi
-}
-
-Inform()
-{
- Log 1 -e "\x1B[0;34m$@\x1B[m"
-}
-
-Debug()
-{
- Log 2 -e "\x1B[0;32m$@\x1B[m"
-}
-
-Error()
-{
- >&2 Log 0 -e "\x1B[0;31m$@\x1B[m"
-}
-
-Fetch()
-{
- URL=$1
- FILE=$2
- PROGRESS=$3
- if [ $VERBOSE -ge 1 ] && [ $PROGRESS ]; then
- CURL_OPT="--progress-bar"
- else
- CURL_OPT="--silent"
- fi
- curl $CURL_OPT $URL > $FILE
-}
-
-hash curl 2> /dev/null || { Error "Require 'curl' Aborting."; exit 1; }
-hash xmllint 2> /dev/null || { Error "Require 'xmllint' Aborting."; exit 1; }
-hash sha256sum 2> /dev/null || { Error "Require 'sha256sum' Aborting."; exit 1; }
-
-TMPDIR=$1
-if [ ! -d $TMPDIR ]; then
- TMPDIR=./tizen_tmp
- Debug "Create temporary directory : $TMPDIR"
- mkdir -p $TMPDIR
-fi
-
-TIZEN_URL=http://download.tizen.org/releases/daily/tizen
-BUILD_XML=build.xml
-REPOMD_XML=repomd.xml
-PRIMARY_XML=primary.xml
-TARGET_URL="http://__not_initialized"
-
-Xpath_get()
-{
- XPATH_RESULT=''
- XPATH=$1
- XML_FILE=$2
- RESULT=$(xmllint --xpath $XPATH $XML_FILE)
- if [[ -z ${RESULT// } ]]; then
- Error "Can not find target from $XML_FILE"
- Debug "Xpath = $XPATH"
- exit 1
- fi
- XPATH_RESULT=$RESULT
-}
-
-fetch_tizen_pkgs_init()
-{
- TARGET=$1
- PROFILE=$2
- Debug "Initialize TARGET=$TARGET, PROFILE=$PROFILE"
-
- TMP_PKG_DIR=$TMPDIR/tizen_${PROFILE}_pkgs
- if [ -d $TMP_PKG_DIR ]; then rm -rf $TMP_PKG_DIR; fi
- mkdir -p $TMP_PKG_DIR
-
- PKG_URL=$TIZEN_URL/$PROFILE/latest
-
- BUILD_XML_URL=$PKG_URL/$BUILD_XML
- TMP_BUILD=$TMP_PKG_DIR/$BUILD_XML
- TMP_REPOMD=$TMP_PKG_DIR/$REPOMD_XML
- TMP_PRIMARY=$TMP_PKG_DIR/$PRIMARY_XML
- TMP_PRIMARYGZ=${TMP_PRIMARY}.gz
-
- Fetch $BUILD_XML_URL $TMP_BUILD
-
- Debug "fetch $BUILD_XML_URL to $TMP_BUILD"
-
- TARGET_XPATH="//build/buildtargets/buildtarget[@name=\"$TARGET\"]/repo[@type=\"binary\"]/text()"
- Xpath_get $TARGET_XPATH $TMP_BUILD
- TARGET_PATH=$XPATH_RESULT
- TARGET_URL=$PKG_URL/$TARGET_PATH
-
- REPOMD_URL=$TARGET_URL/repodata/repomd.xml
- PRIMARY_XPATH='string(//*[local-name()="data"][@type="primary"]/*[local-name()="location"]/@href)'
-
- Fetch $REPOMD_URL $TMP_REPOMD
-
- Debug "fetch $REPOMD_URL to $TMP_REPOMD"
-
- Xpath_get $PRIMARY_XPATH $TMP_REPOMD
- PRIMARY_XML_PATH=$XPATH_RESULT
- PRIMARY_URL=$TARGET_URL/$PRIMARY_XML_PATH
-
- Fetch $PRIMARY_URL $TMP_PRIMARYGZ
-
- Debug "fetch $PRIMARY_URL to $TMP_PRIMARYGZ"
-
- gunzip $TMP_PRIMARYGZ
-
- Debug "unzip $TMP_PRIMARYGZ to $TMP_PRIMARY"
-}
-
-fetch_tizen_pkgs()
-{
- ARCH=$1
- PACKAGE_XPATH_TPL='string(//*[local-name()="metadata"]/*[local-name()="package"][*[local-name()="name"][text()="_PKG_"]][*[local-name()="arch"][text()="_ARCH_"]]/*[local-name()="location"]/@href)'
-
- PACKAGE_CHECKSUM_XPATH_TPL='string(//*[local-name()="metadata"]/*[local-name()="package"][*[local-name()="name"][text()="_PKG_"]][*[local-name()="arch"][text()="_ARCH_"]]/*[local-name()="checksum"]/text())'
-
- for pkg in ${@:2}
- do
- Inform "Fetching... $pkg"
- XPATH=${PACKAGE_XPATH_TPL/_PKG_/$pkg}
- XPATH=${XPATH/_ARCH_/$ARCH}
- Xpath_get $XPATH $TMP_PRIMARY
- PKG_PATH=$XPATH_RESULT
-
- XPATH=${PACKAGE_CHECKSUM_XPATH_TPL/_PKG_/$pkg}
- XPATH=${XPATH/_ARCH_/$ARCH}
- Xpath_get $XPATH $TMP_PRIMARY
- CHECKSUM=$XPATH_RESULT
-
- PKG_URL=$TARGET_URL/$PKG_PATH
- PKG_FILE=$(basename $PKG_PATH)
- PKG_PATH=$TMPDIR/$PKG_FILE
-
- Debug "Download $PKG_URL to $PKG_PATH"
- Fetch $PKG_URL $PKG_PATH true
-
- echo "$CHECKSUM $PKG_PATH" | sha256sum -c - > /dev/null
- if [ $? -ne 0 ]; then
- Error "Fail to fetch $PKG_URL to $PKG_PATH"
- Debug "Checksum = $CHECKSUM"
- exit 1
- fi
- done
-}
-
-Inform "Initialize arm base"
-fetch_tizen_pkgs_init standard base
-Inform "fetch common packages"
-fetch_tizen_pkgs armv7l glibc glibc-devel
-fetch_tizen_pkgs noarch linux-glibc-devel
-fetch_tizen_pkgs armv7l libgcc libstdc++ libstdc++-devel libunwind libunwind-devel
-
-
-Inform "Initialize standard unified"
-fetch_tizen_pkgs_init standard unified
-Inform "fetch nnfw packages"
-fetch_tizen_pkgs armv7l gmock-devel tensorflow-lite-devel boost-devel libarmcl-devel boost-program-options boost-system boost-filesystem gmock libarmcl
-
diff --git a/tools/cross/armel/tizen.patch b/tools/cross/armel/tizen.patch
deleted file mode 100644
index d223427c9..000000000
--- a/tools/cross/armel/tizen.patch
+++ /dev/null
@@ -1,18 +0,0 @@
-diff -u -r a/usr/lib/libc.so b/usr/lib/libc.so
---- a/usr/lib/libc.so 2016-12-30 23:00:08.284951863 +0900
-+++ b/usr/lib/libc.so 2016-12-30 23:00:32.140951815 +0900
-@@ -2,4 +2,4 @@
- Use the shared library, but some functions are only in
- the static library, so try that secondarily. */
- OUTPUT_FORMAT(elf32-littlearm)
--GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a AS_NEEDED ( /lib/ld-linux.so.3 ) )
-+GROUP ( libc.so.6 libc_nonshared.a AS_NEEDED ( ld-linux.so.3 ) )
-diff -u -r a/usr/lib/libpthread.so b/usr/lib/libpthread.so
---- a/usr/lib/libpthread.so 2016-12-30 23:00:19.408951841 +0900
-+++ b/usr/lib/libpthread.so 2016-12-30 23:00:39.068951801 +0900
-@@ -2,4 +2,4 @@
- Use the shared library, but some functions are only in
- the static library, so try that secondarily. */
- OUTPUT_FORMAT(elf32-littlearm)
--GROUP ( /lib/libpthread.so.0 /usr/lib/libpthread_nonshared.a )
-+GROUP ( libpthread.so.0 libpthread_nonshared.a )
diff --git a/tools/cross/install_rootfs.sh b/tools/cross/install_rootfs.sh
index 16f3a5cad..7af7bf711 100755
--- a/tools/cross/install_rootfs.sh
+++ b/tools/cross/install_rootfs.sh
@@ -2,9 +2,8 @@
usage()
{
echo "Usage: $0 [BuildArch] [LinuxCodeName] [--setproxy=IP] [--skipunmount]"
- echo "BuildArch can be: arm(default), aarch64 and armel"
- echo "LinuxCodeName - optional, Code name for Linux, can be: bionic(default), focal, jammy"
- echo " If BuildArch is armel, this can be tizen(default)"
+ echo "BuildArch can be: arm(default), aarch64"
+ echo "LinuxCodeName - optional, Code name for Linux, can be: bionic, focal(default), jammy"
echo "--setproxy=IP - optional, IP is the proxy server IP address or url with portnumber"
echo " default no proxy. Example: --setproxy=127.1.2.3:8080"
echo "--skipunmount - optional, will skip the unmount of rootfs folder."
@@ -17,7 +16,7 @@ __UbuntuRepo="http://ports.ubuntu.com/"
__BuildArch=arm
__QemuArch=armhf
-__LinuxCodeName=bionic
+__LinuxCodeName=focal
__SkipUnmount=0
__IsProxySet=0
__Apt=""
@@ -52,24 +51,6 @@ for i in "$@" ; do
__BuildArch=aarch64
__QemuArch=arm64
;;
- armel)
- __BuildArch=armel
- __Tizen=tizen
- __QemuArch=
- __UbuntuRepo=
- __LinuxCodeName=
- ;;
- tizen)
- if [ "$__BuildArch" != "armel" ]; then
- echo "Tizen rootfs is available only for armel."
- usage;
- exit 1;
- fi
- __Tizen=tizen
- __QemuArch=
- __UbuntuRepo=
- __LinuxCodeName=
- ;;
bionic)
__LinuxCodeName=bionic
;;
@@ -110,7 +91,7 @@ if [ -d "$__RootfsDir" ]; then
rm -rf $__RootfsDir
fi
-if [ $__IsProxySet == 1 ] && [ "$__Tizen" != "tizen" ]; then
+if [ $__IsProxySet == 1 ]; then
mkdir -p $__RootfsDir/etc/apt/apt.conf.d
echo -e "$__Apt" >> $__RootfsDir/etc/apt/apt.conf.d/90proxy
fi
@@ -129,8 +110,6 @@ if [[ -n $__LinuxCodeName ]]; then
if [ $__SkipUnmount == 0 ]; then
umount $__RootfsDir/*
fi
-elif [ "$__Tizen" == "tizen" ]; then
- ROOTFS_DIR=$__RootfsDir $__CrossDir/$__BuildArch/tizen-build-rootfs.sh
else
echo "Unsupported target platform."
usage;
diff --git a/tools/generate_datafile/tf_dataset_converter/README.md b/tools/generate_datafile/tf_dataset_converter/README.md
new file mode 100644
index 000000000..3d4612520
--- /dev/null
+++ b/tools/generate_datafile/tf_dataset_converter/README.md
@@ -0,0 +1,66 @@
+# tf dataset converter
+
+## What is tf dataset converter?
+
+_tf dataset converter_ is a tool which converts tensorflow datasets to datasets for `onert_train`.
+
+## Possible datasets
+- Tensorflow datasets with [ClassLabel feature](https://www.tensorflow.org/datasets/api_docs/python/tfds/features/ClassLabel)
+
+## Prerequisite
+- Python 3.8 (python3.8, python3.8-dev packages)
+- Python packages required
+
+## Usage
+usage: main.py [-h] [-s] [-d Dataset] [-o Dir] [-p Prefix] [-l N] [-t N]
+
+Convert a dataset of tensorflow to onert format
+
+options:
+ -h, --help show this help message and exit
+ -s, --show-datasets show dataset list
+ -d Dataset, --dataset-name Dataset
+ name of dataset to be converted (default: "fashion_mnist")
+ -o Dir, --out-dir Dir
+ relative path of the files to be created (default: "out")
+ -p Prefix, --prefix-name Prefix
+ prefix name of the file to be created (default: "")
+ -l N, --train-length N
+ Number of data for training (default: 1000)
+ -t N, --test-length N
+ Number of data for training (default: 100)
+
+## Example
+### Install required packages
+```
+$ python3 -m pip install -r requirements.txt
+```
+
+### Show dataset list
+```
+$ python3 main.py --show-datasets
+Dataset list :
+[abstract_reasoning,
+accentdb,
+...
+fashion_mnist,
+...
+robotics:mt_opt_sd]
+```
+
+### Convert dataset to onert format
+```
+$ python3 main.py \
+ --dataset-name fashion_mnist \
+ --prefix-name fashion-mnist \
+ --train-length 2000 \
+ --test-length 200
+```
+```
+$ tree out
+out
+├── fashion-mnist.test.input.200.bin
+├── fashion-mnist.test.output.200.bin
+├── fashion-mnist.train.input.2000.bin
+└── fashion-mnist.train.output.2000.bin
+```
diff --git a/tools/generate_datafile/tf_dataset_converter/argparser.py b/tools/generate_datafile/tf_dataset_converter/argparser.py
new file mode 100644
index 000000000..daa7b5f07
--- /dev/null
+++ b/tools/generate_datafile/tf_dataset_converter/argparser.py
@@ -0,0 +1,54 @@
+'''Parse arguments'''
+
+import argparse
+
+
+def _create_parser():
+ parser = argparse.ArgumentParser(
+ description='Convert a dataset of tensorflow to onert format')
+ parser.add_argument(
+ '-s', '--show-datasets', action='store_true', help='show dataset list')
+ parser.add_argument(
+ '-d',
+ '--dataset-name',
+ type=str,
+ default='fashion_mnist',
+ metavar='Dataset',
+ help='name of dataset to be converted (default: "fashion_mnist")')
+ parser.add_argument(
+ '-o',
+ '--out-dir',
+ type=str,
+ default='out',
+ metavar='Dir',
+ help='relative path of the files to be created (default: "out")')
+ parser.add_argument(
+ '-p',
+ '--prefix-name',
+ type=str,
+ default='',
+ metavar='Prefix',
+ help='prefix name of the file to be created (default: "")')
+ parser.add_argument(
+ '-l',
+ '--train-length',
+ type=int,
+ default=1000,
+ metavar='N',
+ help='Number of data for training (default: 1000)')
+ parser.add_argument(
+ '-t',
+ '--test-length',
+ type=int,
+ default=100,
+ metavar='N',
+ help='Number of data for training (default: 100)')
+
+ return parser
+
+
+def parse_args():
+ parser = _create_parser()
+ args = parser.parse_args()
+
+ return args
diff --git a/tools/generate_datafile/tf_dataset_converter/datasets.py b/tools/generate_datafile/tf_dataset_converter/datasets.py
new file mode 100644
index 000000000..d63320055
--- /dev/null
+++ b/tools/generate_datafile/tf_dataset_converter/datasets.py
@@ -0,0 +1,80 @@
+'''Deal with the tensorflow dataset.'''
+
+import tensorflow as tf
+import tensorflow_datasets as tfds
+from pathlib import Path
+
+dataset_root_dir = Path(__file__).parent.absolute() / 'data'
+
+
+class DatasetLoader():
+ '''
+ Loader of tensorflow datasets
+ '''
+
+ def load(self, dataset_name):
+ (ds_train, ds_test), ds_info = tfds.load(
+ dataset_name,
+ split=['train', 'test'],
+ data_dir=dataset_root_dir,
+ shuffle_files=True,
+ as_supervised=True,
+ with_info=True,
+ )
+
+ self.ds_info = ds_info
+
+ def _normalize_img(image, label):
+ """Normalizes images: `uint8` -> `float32`."""
+ return tf.cast(image, tf.float32) / 255., label
+
+ self.ds_train = ds_train.map(_normalize_img)
+ self.ds_test = ds_test.map(_normalize_img)
+
+ for images, labels in self.ds_train:
+ print(f'Shape of images : {images.shape}')
+ print(f'Shape of labels: {labels.shape} {labels.dtype}')
+ break
+
+ def get_dataset_names(self):
+ return tfds.list_builders()
+
+ def class_names(self):
+ '''
+ Get class names
+ '''
+ return self.ds_info.features['label'].names
+
+ def num_classes(self):
+ '''
+ Get the number of classes
+ '''
+ return self.ds_info.features['label'].num_classes
+
+ def get_num_train_examples(self):
+ '''
+ Get examples for training
+ '''
+ return self.ds_info.splits['train'].num_examples
+
+ def get_num_test_examples(self):
+ '''
+ Get examples for testing
+ '''
+ return self.ds_info.splits['test'].num_examples
+
+ def prefetched_datasets(self):
+ '''
+ get prefetched datasets for traning.
+
+ Return:
+ Datasets for training and testing.
+ '''
+
+ train_dataset = self.ds_train.cache()
+ train_dataset = train_dataset.shuffle(self.ds_info.splits['train'].num_examples)
+
+ test_dataset = self.ds_train.cache()
+
+ # return train_dataset, test_dataset
+ return self.ds_train.cache(), self.ds_test.cache()
diff --git a/tools/generate_datafile/tf_dataset_converter/main.py b/tools/generate_datafile/tf_dataset_converter/main.py
new file mode 100644
index 000000000..77e339965
--- /dev/null
+++ b/tools/generate_datafile/tf_dataset_converter/main.py
@@ -0,0 +1,98 @@
+################################################################################
+# Parse arguments
+################################################################################
+
+from argparser import parse_args
+
+# You can see arguments' information in argparser.py
+args = parse_args()
+
+################################################################################
+# Load a dataset of tensorflow
+################################################################################
+
+# Disable tensorflow cpp warning log
+import os
+
+FILTERING_WARNING = '2'
+os.environ['TF_CPP_MIN_LOG_LEVEL'] = FILTERING_WARNING
+
+from datasets import DatasetLoader
+from pathlib import Path
+import tensorflow as tf
+import numpy as np
+
+ds_loader = DatasetLoader()
+
+if args.show_datasets:
+ print('Dataset list :')
+ names = ',\n'.join(ds_loader.get_dataset_names())
+ print(f'[{names}]')
+ exit(0)
+
+ds_loader.load(args.dataset_name)
+ds_train, ds_test = ds_loader.prefetched_datasets()
+nums_train_ds = ds_loader.get_num_train_examples()
+nums_test_ds = ds_loader.get_num_test_examples()
+print(f'class names : {ds_loader.class_names()}')
+print(f'train dataset len : {nums_train_ds}')
+print(f'test dataset len : {nums_test_ds}')
+
+################################################################################
+# Convert tensorlfow dataset to onert format
+################################################################################
+Path(f'{args.out_dir}').mkdir(parents=True, exist_ok=True)
+prefix_name = f'{args.out_dir}/{args.prefix_name}'
+if args.prefix_name != '':
+ prefix_name += '.'
+
+nums_train = args.train_length
+if (nums_train > nums_train_ds):
+ print(
+ f'Oops! The number of data for training in the dataset is less than {nums_train}')
+ exit(1)
+
+nums_test = args.test_length
+if (nums_test > nums_test_ds):
+ print(f'Oops! The number of data for test in the dataset is less than {nums_test}')
+ exit(1)
+
+
+def _only_image(image, _):
+ return image
+
+
+def _only_label(_, label):
+ return label
+
+
+def _label_to_array(label):
+ arr = np.zeros(ds_loader.num_classes(), dtype=float)
+ arr[label] = 1.
+ tensor = tf.convert_to_tensor(arr, tf.float32)
+ return tensor
+
+
+file_path_list = [
+ f'{prefix_name}train.input.{nums_train}.bin',
+ f'{prefix_name}test.input.{nums_test}.bin',
+ f'{prefix_name}train.output.{nums_train}.bin',
+ f'{prefix_name}test.output.{nums_test}.bin'
+]
+
+ds_list = [
+ ds_train.take(nums_train).map(_only_image),
+ ds_test.take(nums_test).map(_only_image),
+ [_label_to_array(label) for label in ds_train.take(nums_train).map(_only_label)],
+ [_label_to_array(label) for label in ds_test.take(nums_test).map(_only_label)]
+]
+
+for i in range(4):
+ file_path = file_path_list[i]
+ with open(file_path, 'wb') as f:
+ ds = ds_list[i]
+ for tensor in ds:
+ f.write(tensor.numpy().tobytes())
+ f.close()
+
+print('The data files are created!')
diff --git a/tools/generate_datafile/tf_dataset_converter/requirements.txt b/tools/generate_datafile/tf_dataset_converter/requirements.txt
new file mode 100644
index 000000000..c34025fe6
--- /dev/null
+++ b/tools/generate_datafile/tf_dataset_converter/requirements.txt
@@ -0,0 +1,8 @@
+argparse
+numpy
+pathlib
+# Please upgrade pip version before installing these requerements.
+# pip 20.2 and earlier doesn’t have true dependency resolution.
+# Refer to https://pip.pypa.io/en/latest/user_guide/#requirements-files
+tensorflow==2.8.2 # This version specifies the upper bound for protobuf
+tensorflow_datasets==4.7.0